【JDBC实战】水果库存系统 [功能实现](接口实现类FruitDAOImpl的功能实现)万字长文

CSDN话题挑战赛第2期
参赛话题:学习笔记

在这里插入图片描述

JDBC专栏

(点击进入专栏)
【1】idea添加mysql-jar包
【2】使用IDEA连接数据库,执行增删改操作。
【3】IDEA连接数据库,执行查询操作,返回结果集并输出。
【4】JDBC实战 水果库存系统 [设计阶段]
【5】水果库存系统 [功能实现](接口实现类FruitDAOImpl)
【7】 水果库存系统 [代码优化]
【8】连接数据库,执行批处理操作。
【9】数据库连接池:德鲁伊druid的使用


JDBC实战,实现水果库存系统

  • JDBC专栏
  • 前言
  • 接口实现类FruitDAOImpl的功能实现
    • 一、更新操作相关
      • 1. boolean addFruit(Fruit fruit);
      • 2.boolean UpdateFruit(Fruit fruit);
      • 3.boolean DelFruit(String fname)
    • 二、查询操作相关
      • 1.List getFruitList()
      • 2.Fruit getFruitByFname(String fname)
    • 三、代码汇总


前言

上一篇文章中,我们对水果库存系统的需求进行了介绍,同时对系统需要的结构进行了设计,接下来,就到了实际上手,实现功能的阶段了。
在这篇文章中,我们将对实现类FruitDAOImpl中的单精度方法进行代码实现。

回顾一下实现类FruitDAOImpl中设计的单精度方法吧:

查询库存列表:

  • List< Fruit > getFruitList();

新增库存:

  • boolean addFruit(Fruit fruit);

修改库存:

  • boolean UpdateFruit(Fruit fruit);

删除库存:

  • boolean DelFruit(String fname);

查询指定库存:

  • Fruit getFruitByFname(String fname);

接口实现类FruitDAOImpl的功能实现

一、更新操作相关

1. boolean addFruit(Fruit fruit);

这是新增库存的方法,根据字面意思来简单理解一下,就是使用JDBC连接数据库,对数据库数据进行增添操作,增添的数据来自传入的Fruit对象。

依旧是常规的步骤:

加载驱动

//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");


使用数据库管理器,连接数据库
需要准备:
连接数据库的地址URL;
数据库账户USER;
账户密码PSW(password);

String URL = "jdbc:mysql://localhost:3306/fruitdb?useSSL=false&useUnicode=true&CharacterEncoding=utf-8";
String USER = "root" ;
String PSW = "" ;
 //数据库管理器,连接数据库
Connection  connection = DriverManager.getConnection(URL, USER, PSW);


编写SQL语句
因为第一个属性fid(水果编号)是自增列,所以填入0即可。
剩下的四个属性,使用占位符 ?代替,以便后续的填充。

String sql = "insert into t_fruit values(0,?,?,?,?)";


创建预处理对象

将编写的SQL语句传入;

 PreparedStatement pstm = connection.prepareStatement(sql);


填充占位符 ?参数
这里面的参数需要从传入的Fruit对象中获取,也就是:

  • fruit.getFname()
  • fruit.getPrice()
  • fruit.getFcount()
  • fruit.getRemark()
pstm.setString(1, fruit.getFname());
pstm.setInt(2,fruit.getPrice());
pstm.setInt(3,fruit.getFcount());
pstm.setString(4,fruit.getRemark());


执行更新,返回影响行数

int count = pstm.executeUpdate()

因为boolean addFruit(Fruit fruit);方法的返回值是布尔类型(boolean),所以当返回的影响行数大于零时,我们就返回true,否则返回false

return count > 0;


关闭资源
很重要的一步:

psmt.close();
connection.close();


完成这一系列的操作,我们得到了:

【JDBC实战】水果库存系统 [功能实现](接口实现类FruitDAOImpl的功能实现)万字长文_第1张图片

满屏的报错,对了,我们还需要异常处理try-catch-finally

    @Override
    public boolean addFruit(Fruit fruit){
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/fruitdb?useSSL=false&useUnicode=true&characterEncoding=gbk",
                    "root", "");

            String sql = "insert into t_fruit values(8,?,?,?,?)";
            PreparedStatement psmt = connection.prepareStatement(sql);

            pstm.setString(1, fruit.getFname());
            pstm.setInt(2,fruit.getPrice());
            pstm.setInt(3,fruit.getFcount());
            pstm.setString(4,fruit.getRemark());

            int count = psmt.executeUpdate();
            
            return count > 0;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally{
            
            try {
                if(psmt != null)
                psmt.close();
                if(connection != null)
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

但是,依旧爆红

【JDBC实战】水果库存系统 [功能实现](接口实现类FruitDAOImpl的功能实现)万字长文_第2张图片

这是因为我们经过异常处理之后,创建的对象,都被try{}代码块给囊括起来了,而出了代码块之后也就失去了效用,所以在finally{}中的对象会出问题…

为了解决这个问题,我们就需要将对象都设置成全局变量,这样的话,无论在那个代码块中,都能被识别出来。
同时,还可以将一些比较冗长,常常用到的属性也设置成全局变量,方便使用。

    final String DRIVER = "com.mysql.cj.jdbc.Driver";
    final String URL = "jdbc:mysql://localhost:3306/fruitdb?useSSL=false&useUnicode=true&CharacterEncoding=utf-8";
    final String USER = "root" ;
    final String PSW = "" ;
    Connection connection;
    PreparedStatement pstm;
    ResultSet rs;
    List<Fruit> list;

这样子,问题基本就解决啦:

【JDBC实战】水果库存系统 [功能实现](接口实现类FruitDAOImpl的功能实现)万字长文_第3张图片

    @Override
    public boolean addFruit(Fruit fruit){

        try {

            Class.forName(DRIVER);
            connection = DriverManager.getConnection(URL, USER, PSW);

            String sql = "insert into t_fruit values(0,?,?,?,?)";

            pstm = connection.prepareStatement(sql);
            pstm.setString(1, fruit.getFname());
            pstm.setInt(2,fruit.getPrice());
            pstm.setInt(3,fruit.getFcount());
            pstm.setString(4,fruit.getRemark());

            return pstm.executeUpdate() > 0;
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }


上文介绍的功能实现,步骤已经十分齐全,而且在接下来的更新操作相关方法中,除了SQL语句,基本上都大同小异了。

2.boolean UpdateFruit(Fruit fruit);

在更新水果库存方法中,我们只需要更新指定水果的库存数量即可,所以需要填充的参数有两个,都是从传入的Fruit对象(已修改库存)中获取:

  • fruit.getFname() — 获取水果名称
  • fruit.getFcount() — 获取水果库存

功能实现代码:

 @Override
    public boolean UpdateFruit(Fruit fruit) {
        try {
        //加载驱动
        Class.forName(DRIVER);
        //数据库管理器,连接数据库
        connection = DriverManager.getConnection(URL, USER, PSW);
        //sql语句
        String sql = "update t_fruit set fcount = ? where fname like ?";
        //预处理对象
        pstm = connection.prepareStatement(sql);
        pstm.setInt(1,fruit.getFcount());
        pstm.setString(2, fruit.getFname());

        return pstm.executeUpdate() > 0;

    } catch (ClassNotFoundException | SQLException e) {
        e.printStackTrace();
    }finally{
        try {
            if(pstm != null)
                pstm.close();
            if(connection != null)
                connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
        return false;
    }


3.boolean DelFruit(String fname)

删除库存的方法里,只需要根据传入的水果名称,删除数据库中相应的数据即可:

功能实现的代码

 @Override
    public boolean DelFruit(String fname) {
        try {
            //加载驱动
            Class.forName(DRIVER);
            //数据库管理器,连接数据库
            connection = DriverManager.getConnection(URL, USER, PSW);
            //sql语句
            String sql = "delete from t_fruit where fname like ?";
            //预处理对象
            pstm = connection.prepareStatement(sql);
            pstm.setString(1,fname);

            return pstm.executeUpdate() > 0;

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;

    }



二、查询操作相关

1.List getFruitList()

执行查询操作与执行更新操作之间有一定的差异

查询操作通常调用的是预处理对象的executeQuery()方法
更新操作通常调用的是预处理对象的executeUpdate()方法

executeUpdate()方法返回的是更新操作后的影响行数;
executeQuery()方法返回的是一个 ResultSet对象,里面存储的是记录了数据库每行信息的数据。

我们需要使用循环来将数据库每行信息记录下来,存储进数组中返回。

集合在上文已经设置成了全局变量:

    ResultSet rs;     //rs对象
    List<Fruit> list; //集合

查询水果信息的实现代码

@Override
    public List<Fruit> getFruitList() {
        try {
            //加载驱动
            Class.forName(DRIVER);
            //数据库管理器,连接数据库
            connection = DriverManager.getConnection(URL, USER, PSW);
            //sql语句
            String sql = "select * from t_fruit";
            //预处理对象
            pstm = connection.prepareStatement(sql);
            //执行查询,返回结果集
            rs = pstm.executeQuery();
            list = new ArrayList<Fruit>();
            while(rs.next()){
                int Fid = rs.getInt("fid");
                String Fname = rs.getString("fname");
                int Price = rs.getInt("price");
                int Fcount = rs.getInt("fcount");
                String Remark = rs.getString("remark");
                Fruit fruitTable = new Fruit(Fid,Fname,Price,Fcount,Remark);
                list.add(fruitTable);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            try {
                if(rs != null)
                    rs.close();
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return list;
    }


2.Fruit getFruitByFname(String fname)

查询指定水果的信息,在这个方法中,我们依靠传入的水果姓名-fname来确定需要查询信息的水果。

返回的是Fruit对象,此对象的属性便是指定水果的信息。

@Override
    public Fruit getFruitByFname(String fname) {
        try {
            //加载驱动
            Class.forName(DRIVER);
            //数据库管理器,连接数据库
            connection = DriverManager.getConnection(URL, USER, PSW);
            //sql语句
            String sql = "select * from t_fruit where fname = ? ";
            //预处理对象
            pstm = connection.prepareStatement(sql);
            pstm.setString(1,fname);
            //执行查询,返回结果集
            rs = pstm.executeQuery();
            while(rs.next()){
                int fid = rs.getInt("fid");
                int price = rs.getInt("price");
                int fcount = rs.getInt("fcount");
                String remark = rs.getString("remark");
                Fruit fruit = new Fruit(fid,fname,price,fcount,remark);
                return fruit;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            try {
                if(rs != null)
                    rs.close();
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


三、代码汇总

接口实现类FruitDAOImpl中出现的方法,全都是单精度方法,代表方法的颗粒密度已经不能再划分了。

简单点来说,方法的功能还过于单一,操作过于简易,而不足以满足水果库存系统的功能需求。

也正因如此,我们还需要菜单类Menu中的方法,里面的方法调用了接口实现类FruitDAOImpl这里的单精度方法,同时将拥有更加丰富的功能。

接口实现类FruitDAOImpl的功能实现:

import com.haojin.fruit.dao.FruitDAO;
import com.haojin.fruit.pojo.Fruit;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author .29.
 * @create 2022-09-23 17:56
 */
public class FruitDAOImpl implements FruitDAO {
    final String DRIVER = "com.mysql.cj.jdbc.Driver";
    final String URL = "jdbc:mysql://localhost:3306/fruitdb?useSSL=false&useUnicode=true&CharacterEncoding=utf-8";
    final String USER = "root" ;
    final String PSW = "" ;
    Connection connection;
    PreparedStatement pstm;
    ResultSet rs;
    List<Fruit> list;

    @Override
    public List<Fruit> getFruitList() {
        try {
            //加载驱动
            Class.forName(DRIVER);
            //数据库管理器,连接数据库
            connection = DriverManager.getConnection(URL, USER, PSW);
            //sql语句
            String sql = "select * from t_fruit";
            //预处理对象
            pstm = connection.prepareStatement(sql);
            //执行查询,返回结果集
            rs = pstm.executeQuery();
            list = new ArrayList<Fruit>();
            while(rs.next()){
                int Fid = rs.getInt("fid");
                String Fname = rs.getString("fname");
                int Price = rs.getInt("price");
                int Fcount = rs.getInt("fcount");
                String Remark = rs.getString("remark");
                Fruit fruitTable = new Fruit(Fid,Fname,Price,Fcount,Remark);
                list.add(fruitTable);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            try {
                if(rs != null)
                    rs.close();
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    @Override
    public boolean addFruit(Fruit fruit){
        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(URL, USER, PSW);

            String sql = "insert into t_fruit values(0,?,?,?,?)";

            pstm = connection.prepareStatement(sql);
            pstm.setString(1, fruit.getFname());
            pstm.setInt(2,fruit.getPrice());
            pstm.setInt(3,fruit.getFcount());
            pstm.setString(4,fruit.getRemark());

            return pstm.executeUpdate() > 0;
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    @Override
    public boolean UpdateFruit(Fruit fruit) {
        try {
        //加载驱动
        Class.forName(DRIVER);
        //数据库管理器,连接数据库
        connection = DriverManager.getConnection(URL, USER, PSW);
        //sql语句
        String sql = "update t_fruit set fcount = ? where fname like ?";
        //预处理对象
        pstm = connection.prepareStatement(sql);
        pstm.setInt(1,fruit.getFcount());
        pstm.setString(2, fruit.getFname());

        return pstm.executeUpdate() > 0;

    } catch (ClassNotFoundException | SQLException e) {
        e.printStackTrace();
    }finally{
        try {
            if(pstm != null)
                pstm.close();
            if(connection != null)
                connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
        return false;
    }

    @Override
    public boolean DelFruit(String fname) {
        try {
            //加载驱动
            Class.forName(DRIVER);
            //数据库管理器,连接数据库
            connection = DriverManager.getConnection(URL, USER, PSW);
            //sql语句
            String sql = "delete from t_fruit where fname like ?";
            //预处理对象
            pstm = connection.prepareStatement(sql);
            pstm.setString(1,fname);

            return pstm.executeUpdate() > 0;

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;

    }

    @Override
    public Fruit getFruitByFname(String fname) {
        try {
            //加载驱动
            Class.forName(DRIVER);
            //数据库管理器,连接数据库
            connection = DriverManager.getConnection(URL, USER, PSW);
            //sql语句
            String sql = "select * from t_fruit where fname = ? ";
            //预处理对象
            pstm = connection.prepareStatement(sql);
            pstm.setString(1,fname);
            //执行查询,返回结果集
            rs = pstm.executeQuery();
            while(rs.next()){
                int fid = rs.getInt("fid");
                int price = rs.getInt("price");
                int fcount = rs.getInt("fcount");
                String remark = rs.getString("remark");
                Fruit fruit = new Fruit(fid,fname,price,fcount,remark);
                return fruit;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            try {
                if(rs != null)
                    rs.close();
                if(pstm != null)
                    pstm.close();
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

到这里,接口实现类FruitDAOImpl的功能实现就完成啦…
接下来就是对菜单类Menu的功能实现,再完成菜单类的功能代码,我们的水果库存系统功能就可以说是完成了。之后就可以进入代码优化阶段…

【JDBC实战】水果库存系统 [功能实现](接口实现类FruitDAOImpl的功能实现)万字长文_第4张图片

你可能感兴趣的:(JDBC,intellij-idea,java,数据库,mysql,sql)