使用 jdbc 技术升级水果库存系统

news2024/11/16 16:45:45
  • 抽取执行更新方法
  • 抽取查询方法 —— ResultSetMetaData  
    ResultSetMetaData rsmd = rs.getMetaData();//元数据,结果集的结构数据
  • 抽取查询方法 —— 解析结果集封装成实体对象
  • 提取 获取连接释放资源 的方法
  • 将数据库配置信息转移到配置文件
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
    </dependencies>
package com.csdn.fruit.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Fruit implements Serializable {
    private Integer fid;
    private String fname;
    private Integer price;
    private Integer fcount;
    private String remark;

    public Fruit(String fname, Integer price, Integer fcount, String remark) {
        this.fname = fname;
        this.price = price;
        this.fcount = fcount;
        this.remark = remark;
    }
    @Override
    public String toString() {
        return fname + "\t\t" + price + "\t\t" + fcount + "\t\t" + remark;
    }
}
  •  
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///fruitdb
jdbc.user=root
jdbc.pwd=123456
package com.csdn.mymvc.dao;
import com.csdn.mymvc.util.ClassUtil;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public abstract class BaseDao<T> {

    private String DRIVER;
    private String URL;
    private String USER;
    private String PWD;

    private String entityClassName;

    public BaseDao() {
        // this 是谁? this代表的是 FruitDaoImpl 的实例对象,因为 BaseDao是抽象类,不能直接创建对象,所以 new 的是它的子类对象 FruitDaoImpl
        // this.getClass() 获取的是 FruitDaoImpl 的Class对象
        // getGenericSuperclass() 获取到的是:BaseDao<Fruit>
        // Type 是顶层接口,表示所有的类型。它有一个子接口:ParameterizedType
        ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
        // Actual:实际的
        // getActualTypeArguments() 获取实际的类型参数
        Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
        Type actualTypeArgument = actualTypeArguments[0];

        // System.out.println(actualTypeArgument.getTypeName());//com.csdn.fruit.pojo.Fruit

        entityClassName = actualTypeArgument.getTypeName();

        loadJdbcProperties();
    }

    //加载jdbc.properties文件
    private void loadJdbcProperties() {
        try {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("jdbc.properties");
            Properties properties = new Properties();
            properties.load(inputStream);

            DRIVER = properties.getProperty("jdbc.driver", "com.mysql.cj.jdbc.Driver");
            URL = properties.getProperty("jdbc.url", "jdbc:mysql:///fruitdb");
            USER = properties.getProperty("jdbc.user", "root");
            PWD = properties.getProperty("jdbc.pwd", "123456");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private Connection getConn() {
        try {
            Class.forName(DRIVER);
            return DriverManager.getConnection(URL, USER, PWD);
        } catch (ClassNotFoundException | SQLException e) {
            throw new RuntimeException(e);
        }
    }

    private void close(Connection conn, PreparedStatement psmt, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
            if (psmt != null) {
                psmt.close();
            }
            if (conn != null && !conn.isClosed()) {
                conn.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    //抽取执行更新方法
    //执行更新,返回影响行数
    protected int executeUpdate(String sql, Object... params) {
        PreparedStatement psmt = null;
        Connection conn = null;
        try {
            conn = getConn();
            psmt = conn.prepareStatement(sql);

            setParams(psmt, params);

            return psmt.executeUpdate();

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(conn, psmt, null);
        }
    }

    //设置参数
    private void setParams(PreparedStatement psmt, Object... params) throws SQLException {
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                psmt.setObject(i + 1, params[i]);
            }
        }
    }

    //执行查询,返回集合
    protected List<T> executeQuery(String sql, Object... params) {
        List<T> list = new ArrayList<>();
        Connection conn = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;

        try {
            conn = getConn();
            psmt = conn.prepareStatement(sql);
            setParams(psmt, params);
            rs = psmt.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();//元数据,结果集的结构数据
            while (rs.next()) {
                //T t = new T();  T仅仅是一个符号,所以不能 new
                T t = (T) ClassUtil.createInstance(entityClassName);
                int columnCount = rsmd.getColumnCount();//获取结果集的列的数据
                //jdbc中都是从 1 开始,所以要把 i 改成 从 1 开始
                for (int i = 1; i <= columnCount; i++) {
                    //假设循环 5 次,得到 5 个值,应该对应的是一个对象的 5 个属性的值
                    String columnName = rsmd.getColumnLabel(i);
                    Object columnValue = rs.getObject(i);
                    //给 t 这个对象的 columnName 属性赋 columnValue 值
                    ClassUtil.setProperty(t, columnName, columnValue);
                }
                list.add(t);
            }
            return list;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(conn, psmt, rs);
        }
    }

    protected T load(String sql, Object... params) {

        Connection conn = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;

        try {
            conn = getConn();
            psmt = conn.prepareStatement(sql);
            setParams(psmt, params);
            rs = psmt.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();//元数据,结果集的结构数据
            if (rs.next()) {
                //T t = new T();  T仅仅是一个符号,所以不能 new
                T t = (T) ClassUtil.createInstance(entityClassName);
                int columnCount = rsmd.getColumnCount();//获取结果集的列的数据
                //jdbc中都是从 1 开始,所以要把 i 改成 从 1 开始
                for (int i = 1; i <= columnCount; i++) {
                    //假设循环 5 次,得到 5 个值,应该对应的是一个对象的 5 个属性的值
                    String columnName = rsmd.getColumnLabel(i);
                    Object columnValue = rs.getObject(i);
                    //给 t 这个对象的 columnName 属性赋 columnValue 值
                    ClassUtil.setProperty(t, columnName, columnValue);
                }
                return t;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(conn, psmt, rs);
        }
        return null;
    }
}
package com.csdn.mymvc.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ClassUtil {

    public static Object createInstance(String entityClassName) {
        try {
            return Class.forName(entityClassName).getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException |
                 ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static void setProperty(Object instance, String propertyName, Object propertyValue) {
        Class<?> aClass = instance.getClass();
        try {
            Field field = aClass.getDeclaredField(propertyName);
            field.setAccessible(true);
            field.set(instance, propertyValue);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

 

package com.csdn.fruit.dao;
import com.csdn.fruit.pojo.Fruit;
import java.util.List;
//dao :Data Access Object 数据访问对象
//接口设计
public interface FruitDao {

    void addFruit(Fruit fruit);

    void delFruit(String fname);

    void updateFruit(Fruit fruit);

    List<Fruit> getFruitList();

    Fruit getFruitByFname(String fname);
}
package com.csdn.fruit.dao.impl;
import com.csdn.fruit.dao.FruitDao;
import com.csdn.fruit.pojo.Fruit;
import com.csdn.mymvc.dao.BaseDao;
import java.util.List;
public class FruitDaoImpl extends BaseDao<Fruit> implements FruitDao {
    @Override
    public void addFruit(Fruit fruit) {
        String sql = "insert into t_fruit values (0,?,?,?,?)";
        super.executeUpdate(sql, fruit.getFname(), fruit.getPrice(), fruit.getFcount(), fruit.getRemark());
    }

    @Override
    public void delFruit(String fname) {
        String sql = "delete from t_fruit where fname=?";
        super.executeUpdate(sql, fname);
    }

    @Override
    public void updateFruit(Fruit fruit) {
        String sql = "update  t_fruit set fcount=? where fname = ?";
        super.executeUpdate(sql, fruit.getFcount(), fruit.getFname());

    }

    @Override
    public List<Fruit> getFruitList() {
        return super.executeQuery("select * from t_fruit");
    }

    @Override
    public Fruit getFruitByFname(String fname) {
        return load("select * from t_fruit where fname = ?", fname);
    }
}
package com.csdn.fruit.view;
import com.csdn.fruit.dao.FruitDao;
import com.csdn.fruit.dao.impl.FruitDaoImpl;
import com.csdn.fruit.pojo.Fruit;
import java.util.List;
import java.util.Scanner;
public class Menu {
    Scanner input = new Scanner(System.in);
    private FruitDao fruitDao = new FruitDaoImpl();
    //显示主菜单
    public int showMainMenu() {
        System.out.println("================欢迎使用水果库存系统===================");
        System.out.println("1.显示库存列表");
        System.out.println("2.添加库存记录");
        System.out.println("3.查看特定库存");
        System.out.println("4.水果下架");
        System.out.println("5.退出");
        System.out.println("====================================================");
        System.out.print("请选择:");


        return input.nextInt();
    }
    //显示库存列表
    public void showFruitList() {
        List<Fruit> fruitList = fruitDao.getFruitList();
        System.out.println("----------------------------------------------------");
        System.out.println("名称\t\t单价\t\t库存\t\t备注");
        if (fruitList == null || fruitList.size() <= 0) {
            System.out.println("对不起,库存为空!");
        } else {
               /* fruitList.forEach(new Consumer<Fruit>() {
                @Override
                public void accept(Fruit fruit) {
                    System.out.println(fruit);
                }
            });*/

//            fruitList.forEach(fruit -> System.out.println(fruit));
            fruitList.forEach(System.out::println);
        }
        System.out.println("----------------------------------------------------");
    }
    //添加库存记录
    public void addFruit() {
        System.out.print("请输入水果名称:");
        String fname = input.next();

        Fruit fruit = fruitDao.getFruitByFname(fname);

        if (fruit == null) {
            System.out.print("请输入水果单价:");
            Integer price = input.nextInt();
            System.out.print("请输入水果库存:");
            Integer fcount = input.nextInt();
            System.out.print("请输入水果备注:");
            String remark = input.next();

            fruit = new Fruit(fname, price, fcount, remark);
            fruitDao.addFruit(fruit);
        } else {
            System.out.print("请输入追加的库存量:");
            Integer fcount = input.nextInt();
            fruit.setFcount(fruit.getFcount() + fcount);
            fruitDao.updateFruit(fruit);
        }
        System.out.println("添加成功!");
    }
    //查看特定库存记录
    public void showFruitInfo() {
        System.out.print("请输入水果名称:");
        String fname = input.next();
        Fruit fruit = fruitDao.getFruitByFname(fname);

        if (fruit == null) {
            System.out.println("对不起,没有找到对应的库存记录!");
        } else {
            System.out.println("----------------------------------------------------");
            System.out.println("名称\t\t单价\t\t库存\t\t备注");
            System.out.println(fruit);
            System.out.println("----------------------------------------------------");
        }
    }
    //水果下架
    public void delFruit() {
        System.out.print("请输入水果名称:");
        String fname = input.next();

        Fruit fruit = fruitDao.getFruitByFname(fname);
        if (fruit == null) {
            System.out.println("对不起,没有找到需要下架的库存记录!");
        } else {
            System.out.print("是否确认下架?(Y/N)");
            String confirm = input.next();
            if ("y".equalsIgnoreCase(confirm)) {
                fruitDao.delFruit(fname);
            }

        }
    }
    //退出
    public boolean exit() {
        System.out.print("是否确认退出?(Y/N)");
        String confirm = input.next();
        boolean flag= !"y".equalsIgnoreCase(confirm);
        return flag;
    }
}
package com.csdn.fruit.view;
public class Client {
    public static void main(String[] args) {
        Menu m = new Menu();
        boolean flag = true;
        while (flag) {
            int slt = m.showMainMenu();
            switch (slt) {
                case 1:
                    m.showFruitList();
                    break;
                case 2:
                    m.addFruit();
                    break;
                case 3:
                    m.showFruitInfo();
                    break;
                case 4:
                    m.delFruit();
                    break;
                case 5:
                    //方法设计时是否需要返回值,依据是:是否在调用的地方需要留下一些值用于再运算
                    flag = m.exit();
                    break;
                default:
                    System.out.println("你不按套路出牌!");
                    break;
            }
        }
        System.out.println("谢谢使用!再见!");
    }
}
package com.csdn.dao.impl;
import com.csdn.fruit.dao.FruitDao;
import com.csdn.fruit.dao.impl.FruitDaoImpl;
import com.csdn.fruit.pojo.Fruit;
import org.junit.Test;
import java.util.List;
public class FruitDaoImplTest {

    private FruitDao fruitDao = new FruitDaoImpl();

    @Test
    public void testAddFruit() {
        Fruit fruit = new Fruit("香蕉", 7, 77, "波罗蜜是一种神奇的水果!");
        fruitDao.addFruit(fruit);
    }

    @Test
    public void testDelFruit() {
        fruitDao.delFruit("哈密瓜");
    }

    @Test
    public void testUpdateFruit() {
        Fruit fruit = new Fruit("波罗蜜", 5, 1000, "好吃");
        fruitDao.updateFruit(fruit);
    }

    @Test
    public void testGetFruitList() {
        List<Fruit> fruitList = fruitDao.getFruitList();
        fruitList.stream().forEach(System.out::println);
    }

    @Test
    public void testGetFruitByFname() {

        Fruit fruit = fruitDao.getFruitByFname("波罗蜜");
        System.out.println(fruit);
    }

/*
    // this 是谁? this代表的是 FruitDaoImpl 的实例对象,因为 BaseDao是抽象类,不能直接创建对象,所以 new 的是它的子类对象 FruitDaoImpl
    // this.getClass() 获取的是 FruitDaoImpl 的Class对象
    // getGenericSuperclass() 获取到的是:BaseDao<Fruit>
    // Type 是顶层接口,表示所有的类型。它有一个子接口:ParameterizedType
    ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
    // Actual:实际的
    // getActualTypeArguments() 获取实际的类型参数
    Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
    Type actualTypeArgument = actualTypeArguments[0];

    // System.out.println(actualTypeArgument.getTypeName());//com.csdn.fruit.pojo.Fruit

    entityClassName = actualTypeArgument.getTypeName();

    loadJdbcProperties();
*/
    @Test
    public void testActualTypeArgument() {
            //这个方法是用来测试  actualTypeArgument 实际返回的参数
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1133106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Win11】系统重装教程(最新最详细)

目录 一.简介 二.用U盘制作PE系统 三、安装系统 软件&#xff1a;Windows 11版本&#xff1a;21H2语言&#xff1a;简体中文大小&#xff1a;5.14G安装环境&#xff1a;PE系统&#xff0c;至少7代处理器硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①丨…

10 款超强大性能测试工具,你用过哪几款呢?

这篇关于“性能测试工具”的文章将按以下顺序让您了解不同的软件测试工具&#xff1a; 什么是性能测试&#xff1f; 为什么我们需要性能测试&#xff1f; 性能测试的优势 性能测试的类型 十大性能测试工具 什么是性能测试&#xff1f; 性能测试是一种软件测试&#xff0c;可确…

【Netty专题】用Netty手写一个远程长连接通信框架

目录 前言阅读对象阅读导航前置知识课程内容一、使用Netty实现一个通信框架需要考虑什么问题二、通信框架功能设计2.1 功能描述2.2 通信模型2.3 消息体定义2.4 心跳机制2.5 重连机制*2.6 Handler的组织顺序2.7 交互式调试 三、代码实现&#xff1a;非必要。感兴趣的自行查看3.1…

matlab中narginchk函数用法及其举例

matlab中narginchk函数用法及其举例 narginchk在编写子函数程序时候&#xff0c;在验证输入参数数目方面具有重要作用&#xff0c;本博文讲一讲该函数的用法。 一、narginchk功能 narginchk的作用是验证输入参数数目。 二、语法 narginchk(minArgs,maxArgs)narginchk(minA…

DP读书:《openEuler操作系统》(五)进程与线程

进程与线程 进程的概念程序&#xff1a;从源码到执行1. 编译阶段:2. 加载阶段:3. 执行阶段: 程序的并发执行与进程抽象 进程的描述进程控制块1. 描述信息2. 控制信息3. CPU上下文4. 资源管理信息 进程状态1.就绪状态2.运行状态3.阻塞状态4.终止状态 进程的控制进程控制源语1.创…

第四章 C++的数据类型

系列文章目录 第一章 C的输入第二章 C的输出第三章 C的循环结构 文章目录 系列文章目录前言一、个人名片二、int三、char四、double总结 前言 今天来学数据类型&#xff01; 一、个人名片 个人主页&#xff1a;睡觉觉觉得 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &…

洛谷 P5717 三角形分类 C++代码

目录 前言 题目描述 思路点拨 优化 AC代码 AC截图 结尾 前言 马上就要突破10000浏览量了&#xff0c;再写一篇加加油&#xff01; 图片截图时间:2023.10.25.20:23 题目描述 网址&#xff1a;【深基3.习8】三角形分类 - 洛谷 思路点拨 这道题是给定三条边的长度&#…

BadNets:基于数据投毒的模型后门攻击代码(Pytorch)以MNIST为例

加载数据集 # 载入MNIST训练集和测试集 transform transforms.Compose([transforms.ToTensor(),]) train_loader datasets.MNIST(rootdata,transformtransform,trainTrue,downloadTrue) test_loader datasets.MNIST(rootdata,transformtransform,trainFalse) # 可视化样本 …

[Go版]算法通关村第十八关青铜——透析回溯的模版

目录 认识回溯思想回溯的代码框架从 N 叉树说起有的问题暴力搜索也不行回溯 递归 局部枚举 放下前任Go代码【LeetCode-77. 组合】回溯热身-再论二叉树的路径问题题目&#xff1a;二叉树的所有路径Go 代码 题目&#xff1a;路径总和 IIGo 代码 回溯是最重要的算法思想之一&am…

看我为了水作业速通 opengl freeglut!

参考视频计算机图形学基础–OpenGL的实现_哔哩哔哩_bilibiliT 图形绘制 点 GL_POINTS #define FREEGLUT_STATIC // Define a static library for calling functions #include <GL/freeglut.h> // Include the header filevoid myPoints() { //show three points in sc…

MySQL中大量数据优化方案

文章目录 1 大量数据优化1.1 引言1.2 评估表数据体量1.2.1 表容量1.2.2 磁盘空间1.2.3 实例容量 1.3 出现问题的原因1.4 解决问题1.4.1 数据表分区1.4.1.1 简介1.4.1.2 优缺点1.4.1.2 操作 1.4.2 数据库分表1.4.2.1 简介1.4.2.2 分库分表方案1.4.2.2.1 取模方案1.4.2.2.2 range…

JAVA毕业设计105—基于Java+Springboot+Vue的校园跑腿系统(源码+数据库)

基于JavaSpringbootVue的校园跑腿系统(源码数据库)105 一、系统介绍 本系统前后端分离 本系统分为管理员和用户两个角色 用户&#xff1a; 登录&#xff0c;注册&#xff0c;余额充值&#xff0c;密码修改&#xff0c;发布任务&#xff0c;接受任务&#xff0c;订单管理&…

(多线程)并发编程的三大基础应用——阻塞队列、定时器、线程池【手搓源码】

9.2 阻塞式队列 BlockingQueue<Integer> blockingQueue new LinkedBlockingQueue<Integer>();BlockingQueue<String> queue new LinkedBlockingQueue<>(); // 入队列 queue.put("abc"); // 出队列. 如果没有 put 直接 take, 就会阻塞. St…

IDEA 删除一次性删除所有断点

Ctrl Shift F8 &#xff08;打开“断点”对话框&#xff09; Ctrl A &#xff08;选择所有断点&#xff09; Alt Delete &#xff08;删除选定的断点&#xff09; Enter &#xff08;确认&#xff09;

数字孪生技术:工业数字化转型的引擎

数字孪生是一种将物理实体数字化为虚拟模型的技术&#xff0c;这些虚拟模型与其物理对应物相互关联。这种虚拟模型通常是在数字平台上创建的&#xff0c;它们复制了实际设备、工厂、甚至整个供应链的运作方式。这使工业企业能够实现以下益处&#xff1a; 1. 实时监测和分析 数…

(Java)中的数据类型和变量

文章目录 一、字面常量二、数据类型三、变量1.变量的概念2.语法的格式3.整型变量4.长整型变量5.短整型变量6.字节型变量 四、浮点型变量1.双精度浮点数2.单精度浮点数 五、字符型常量六、布尔型变量七、类型转换1.自动类型转换&#xff08;隐式&#xff09;2.强制类型转换(显式…

【数据结构】数组和字符串(四):特殊矩阵的压缩存储:稀疏矩阵——三元组表

文章目录 4.2.1 矩阵的数组表示4.2.2 特殊矩阵的压缩存储a. 对角矩阵的压缩存储b~c. 三角、对称矩阵的压缩存储d. 稀疏矩阵的压缩存储——三元组表结构体初始化元素设置打印矩阵主函数输出结果代码整合 4.2.1 矩阵的数组表示 【数据结构】数组和字符串&#xff08;一&#xff…

一篇教你学会Ansible

前言 Ansible首次发布于2012年&#xff0c;是一款基于Python开发的自动化运维工具&#xff0c;核心是通过ssh将命令发送执行&#xff0c;它可以帮助管理员在多服务器上进行配置管理和部署。它的工作形式依托模块实现&#xff0c;自己没有批量部署的能力。真正具备批量部署的是…

生产管理中,如何做好生产进度控制?

在生产管理中&#xff0c;我们常常会遇到以下问题&#xff1a; 由于计划不清或者无计划&#xff0c;导致物料进度无法保障&#xff0c;经常出现停工待料的情况。 停工待料导致了生产时间不足&#xff0c;为了赶交货期&#xff0c;只能加班加点。 生产计划并未发挥实际作用&am…

14、Python -- 列表推导式(for表达式)与控制循环

目录 for表达式&#xff08;列表推导式&#xff09;列表推导式的说明使用break跳出循环使用continue忽略本次循环使用return结束函数 列表推导式 使用break跳出循环 使用continue忽略本次循环 for表达式&#xff08;列表推导式&#xff09; for表达式用于利用其他区间、元组、…