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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 了解水果库存系统 [功能实现](接口实现类FruitDAOImpl的功能实现)。

前言


上一篇文章中,我们对水果库存系统的需求进行了介绍,同时对系统需要的结构进行了设计,接下来,就到了实际上手,实现功能的阶段了。

在这篇文章中,我们将对实现类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();

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

微信图片_20221030160519.png

满屏的报错,对了,我们还需要异常处理: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;
    }

  但是,依旧爆红:

微信图片_20221030160527.png


这是因为我们经过异常处理之后,创建的对象,都被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;

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

微信图片_20221030160534.png

@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
 */
 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的功能实现,再完成菜单类的功能代码,我们的水果库存系统功能就可以说是完成了。之后就可以进入代码优化阶段…

微信图片_20221029111446.jpg




相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8月前
|
Java 数据库 数据安全/隐私保护
基于JavaSE+JDBC使用控制台操作的简易购物系统【源码+数据库】
基于JavaSE+JDBC使用控制台操作的简易购物系统【源码+数据库】
104 0
|
4月前
|
SQL 存储 Java
原生JDBC简单实现Mybatis核心功能
本文介绍了在Vertx项目中使用Tdengine时,因缺乏异步JDBC驱动而采用同步驱动结合`vertx.executeBlocking`实现异步查询的方法。文中详细描述了自行开发的一个简易JDBC工具,该工具实现了SQL参数绑定与返回值映射至实体类的功能,简化了原生JDBC的繁琐操作。通过具体示例展示了其实现过程及代码细节,并与原生JDBC进行了对比,突显了其便捷性和实用性。
|
8月前
|
SQL Java 数据库连接
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
66 0
|
8月前
|
Java 关系型数据库 MySQL
基于JDBC的账务管理系统(一)
基于JDBC的账务管理系统
94 0
基于JDBC的账务管理系统(一)
|
8月前
|
机器学习/深度学习 算法 前端开发
基于JDBC的账务管理系统(三)
基于JDBC的账务管理系统
39 0
|
8月前
|
Java 数据库连接
基于JDBC的账务管理系统(二)
基于JDBC的账务管理系统
61 0
|
8月前
|
前端开发 Java BI
Servlet+Jsp+JDBC实现房屋租赁管理系统(源码+数据库+论文+系统详细配置指导+ppt)
Servlet+Jsp+JDBC实现房屋租赁管理系统(源码+数据库+论文+系统详细配置指导+ppt)
110 0
|
3月前
|
Java 关系型数据库 MySQL
mysql5.7 jdbc驱动
遵循上述步骤,即可在Java项目中高效地集成MySQL 5.7 JDBC驱动,实现数据库的访问与管理。
740 1
|
3月前
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
155 0
|
3月前
|
SQL 分布式计算 关系型数据库
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
68 0