JDBC数据库连接---附通用的CRUD类

news2025/2/22 19:59:25

文章目录

  • JDBC数据库连接
    • 1 导包
    • 2 编写配置文件
    • 3 编写连接数据库代码
    • 4 测试工具类
    • 5 附加
      • 1 通用的CRUD类
      • 2 测试CURD类
      • 3 测试

JDBC数据库连接

本篇文章以 MySQL 数据库为例,若要切换其他数据库,只需修改 resource文件夹中的 jdbc.properties 配置文件即可。
项目架构展示:
在这里插入图片描述

1 导包

将MySQL驱动包导入到 lib 目录下,导入之后右键 AS library 将驱动包添加到项目中。否则运行时会报 Class not found 异常。

驱动包下载地址汇总:https://blog.csdn.net/weixin_43671437/article/details/134141851?spm=1001.2014.3001.5501

2 编写配置文件

在Resource 目录下创建 jdbc.properties 配置文件。

## MySQL 8.x
user=root
password=root
url=jdbc:mysql://localhost:3306/jdbc_learn?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true
driverClass=com.mysql.cj.jdbc.Driver 

## SQLServer 连接属性
#url=jdbc:sqlserver://localhost:1433;DatabaseName=SqlMatch2005_5;encrypt=true;trustServerCertificate=true
#driverClass=com.microsoft.sqlserver.jdbc.SQLServerDriver
#user=sa
#password=root

3 编写连接数据库代码

在 java --> util 包内创建一个 JDBCUtil.java 工具类

/**
 * ClassName: JDBCUtil
 * Description: 操作数据库的工具类
 *
 * @Create 2023/10/29 14:35
 * @Version 1.0
 */
public class JDBCUtil {

    /*
      获取数据库连接
     */
    public static Connection getConnection() throws Exception {

        // 1 读取配置文件中的4个信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);

        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");

        // 2 加载驱动
        Class.forName(driverClass);

        // 3 获取连接
        Connection conn = DriverManager.getConnection(url, user, password);

        return conn;
    }

    /**
     * 关闭资源操作,增删改时使用
     * @param conn
     * @param ps
     */
    public static void closeResource(Connection conn, Statement ps){
        // 7 资源关闭
        try {
            if (ps != null)
                ps.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (conn != null)
                conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭资源的操作,查询时使用
     * @param conn
     * @param ps
     * @param rs
     */
    public static void closeResource(Connection conn, Statement ps, ResultSet rs){
        // 7 资源关闭
        try {
            if (ps != null)
                ps.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (conn != null)
                conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

4 测试工具类

测试成功,可以返回一个连接。

    @Test
    public void testConnection6() throws Exception {
        Connection conn = JDBCUtil.getConnection();
        System.out.println(conn);	// com.mysql.cj.jdbc.ConnectionImpl@1cbbffcd
        JDBCUtil.closeResource(conn,null);
    }

5 附加

1 通用的CRUD类

创建 BaseDao.java 类,可直接继承baseDao 来实现对数据库的增删改查。

/**
 * ClassName: BaseDao
 * Description: DAO: data(base) access object 数据库访问对象
 * 封装了针对于数据表的增删改查操作
 *
 * @Create 2023/11/1 13:46
 * @Version 1.0
 */
public abstract class BaseDao<T> {
    private Class<T> clazz = null;

    {
        // 获取当前BaseDao的子类继承父类的泛型
        Type genericSuperclass = this.getClass().getGenericSuperclass();
        ParameterizedType paramType = (ParameterizedType)genericSuperclass; // 获取了父类的泛型参数
        Type[] typeArguments = paramType.getActualTypeArguments();
        clazz = (Class<T>) typeArguments[0]; // 泛型的第一个参数
    }

    /**
     * 通用表的查询方法,但仅能查询条数据
     *
     * @param conn
     * @param sql
     * @param args
     * @return 返回一个对象
     */
    public T getInstance(Connection conn, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            // 为参数赋值
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[0]);
            }
            // 获取结果集
            rs = ps.executeQuery();
            // 获取结果集的元数据:ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            // 通过ResultSetMetaData获取结果集中的列数
            int columnCount = rsmd.getColumnCount();
            if (rs.next()) {
                T t = clazz.newInstance();
                // 处理结果集中的每一列
                for (int i = 0; i < columnCount; i++) {
                    // 获取每一列的列值 通过 ResultSet
                    Object columnValue = rs.getObject(i + 1);
                    // 获取每一列的列名 通过 ResultSetMetaData
                    // 获取列的列名 getColumnName() -- 不推荐使用
                    // 获取列的别名 getColumnLabel() 没有别名时返回列名
                    String columnLabel = rsmd.getColumnLabel(i + 1);

                    // 给T对象指定columnName属性,赋值为columnValue,通过反射
                    // 通俗点说:将customer中的属性与 列名 对应起来 并为属性赋值
                    // 注意;若属性为orderID 列名order_id 此时需要为列名起别名使与属性名一致
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, columnValue); // 赋值
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 资源关闭
            JDBCUtil.closeResource(null, ps, rs);
        }
        return null;
    }

    /**
     * 通用表的查询操作,可返回多条数据。
     *
     * @param conn
     * @param sql
     * @param args
     * @return 返回一个对象集合
     */
    public List<T> getForList(Connection conn, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            // 为参数赋值
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[0]);
            }
            // 获取结果集
            rs = ps.executeQuery();
            // 获取结果集的元数据:ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            // 通过ResultSetMetaData获取结果集中的列数
            int columnCount = rsmd.getColumnCount();
            // 创建集合对象 存储查询的结果
            ArrayList<T> list = new ArrayList<>();
            // 循环遍历每一行数据
            while (rs.next()) {
                T t = clazz.newInstance();
                // 处理结果集中的每一列
                for (int i = 0; i < columnCount; i++) {
                    // 获取每一列的列值 通过 ResultSet
                    Object columnValue = rs.getObject(i + 1);
                    // 获取每一列的列名 通过 ResultSetMetaData
                    // 获取列的列名 getColumnName() -- 不推荐使用
                    // 获取列的别名 getColumnLabel() 没有别名时返回列名
                    String columnLabel = rsmd.getColumnLabel(i + 1);

                    // 给T对象指定columnName属性,赋值为columnValue,通过反射
                    // 通俗点说:将customer中的属性与 列名 对应起来 并为属性赋值
                    // 注意;若属性为orderID 列名order_id 此时需要为列名起别名使与属性名一致
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, columnValue); // 赋值
                }
                list.add(t);
            }
            // 返回数据集合
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 资源关闭
            JDBCUtil.closeResource(null, ps, rs);
        }
        return null;
    }


    /**
     * 通用的 增删改 操作-- version 2.0 增加事务
     *
     * @param conn
     * @param sql
     * @param args
     * @return
     */
    public int updateTable(Connection conn, String sql, Object... args) { // sql中占位符的个数与可变形参的个数相同

        PreparedStatement ps = null;
        try {
            // 2 预编译sql语句,返回PreparedStatement的实例
            ps = conn.prepareStatement(sql);
            // 3 填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]); // 注意参数错误,sql中是从1 开始 数组从0开始
            }
            // 4 执行sql语句
            // boolean execute = ps.execute();
            // if (!execute) System.out.println("执行成功!!!");
            // 返回影响了几行数据
            return ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 修改起为自动提交
            // 主要针对于使用数据库连接池的使用
            try {
                conn.setAutoCommit(true);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }

            // 5 资源关闭
            JDBCUtil.closeResource(null, ps);
        }
        return 0;
    }

    /**
     *  用于查询特殊值的通用方法
     * @param conn
     * @param sql
     * @param args
     * @return
     * @param <E>
     */
    public <E> E getValue(Connection conn, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            // 填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            // 获取查询结果
            rs = ps.executeQuery();
            if (rs.next()) {
                return (E) rs.getObject(1);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(null, ps, rs);
        }
        return null;
    }


}


2 测试CURD类

在Dao层实现对 Customers 类的增删改查以及特殊值的查询
1 创建 CustomersDao.java 接口

/**
 * ClassName: CustomersDao
 * Description: 此接口用于规范 Customers 表的常用操作
 *
 * @Create 2023/11/1 14:06
 * @Version 1.0
 *
 */
public interface CustomersDao {

    /**
     *  将cust对象添加到数据库中
     * @param conn
     * @param cust
     */
    void insert(Connection conn, Customer cust);

    /**
     * 针对指定的id,删除表中的一条记录
     * @param conn
     * @param id
     */
    void deleteById(Connection conn, int id);

    /**
     * 针对内存中的cust对象,去修改数据表中指定的记录
     * @param conn
     * @param cust
     */
    void update(Connection conn, Customer cust);

    /**
     * 根据指定 ID 查询到对象的Customer对象
     * @param conn
     * @param id
     * @return
     */
    Customer getCustomerById(Connection conn,int id);

    /**
     * 返回所有 Customer 对象
     * @param conn
     * @return
     */
    List<Customer> getAllCustomers(Connection conn);

    /**
     * 返回数据表中数据的条目
     * @param conn
     * @return
     */
    Long getCount(Connection conn);

    /**
     * 返回表中最大的生日
     * @param conn
     * @return
     */
    Date getMaxBirth(Connection conn);

}

2 编写CustomersDao接口的实现类
创建 CustomerDaoImpl.java 文件,继承BaseDao并实现CustomersDao接口。

/**
 * ClassName: CustomerDaoImpl
 * Description:
 *
 * @Create 2023/11/1 14:48
 * @Version 1.0
 */
public class CustomerDaoImpl extends BaseDao<Customer> implements CustomersDao {
    @Override
    public void insert(Connection conn, Customer cust) {
        String sql = "insert into customers(name,email,birth) values(?,?,?) ";
        updateTable(conn, sql, cust.getName(), cust.getEmail(), cust.getBirth());
    }

    @Override
    public void deleteById(Connection conn, int id) {
        String sql = "delete from customers where id = ?";
        updateTable(conn, sql, id);
    }

    @Override
    public void update(Connection conn, Customer cust) {
        String sql = "update customers set name = ?, email = ?, birth = ? where id = ?";
        updateTable(conn, sql, cust.getName(),cust.getEmail(),cust.getBirth(),cust.getId());
    }

    @Override
    public Customer getCustomerById(Connection conn, int id) {
        String sql = "select id, name,email,birth from customers where id = ?";
        return getInstance(conn, sql, id);
    }

    @Override
    public List<Customer> getAllCustomers(Connection conn) {
        String sql = "select id, name,email,birth from customers";
        return getForList(conn, sql);
    }

    @Override
    public Long getCount(Connection conn) {
        String sql = "select count(*) from customers";
        return getValue(conn,sql);
    }

    @Override
    public Date getMaxBirth(Connection conn) {
        String sql = "select max(birth) from customers";
        return getValue(conn,sql);
    }
}

3 测试

创建测试类 CustomerDaoImplTest 测试 CustomerDaoImpl


/**
 * ClassName: CustomerDaoImplTest
 * Description:
 *
 * @Create 2023/11/1 15:18
 * @Version 1.0
 */
public class CustomerDaoImplTest {

    private CustomerDaoImpl dao =  new CustomerDaoImpl();

    @Test
    public void insert() {
        Connection conn = null;
        try {
            conn = JDBCUtil.getConnection();
            Customer cust = new Customer(1,"songsong","songsong@163.com",new Date(21312425312L));
            dao.insert(conn,cust);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(conn,null);
        }
    }

    @Test
    public void deleteById() {
        Connection conn = null;
        try {
            conn = JDBCUtil.getConnection();
            dao.deleteById(conn,2);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(conn,null);
        }
    }

    @Test
    public void update() {
        Connection conn = null;
        try {
            conn = JDBCUtil.getConnection();
            Customer cust = new Customer(1,"songsong","songsong@163.com",new Date(21312425312L));
            dao.update(conn,cust);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(conn,null);
        }
    }

    @Test
    public void getCustomerById() {
        Connection conn = null;
        try {
            conn = JDBCUtil.getConnection();
            System.out.println(dao.getCustomerById(conn, 4));
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(conn,null);
        }
    }

    @Test
    public void getAllCustomers() {
        Connection conn = null;
        try {
            conn = JDBCUtil.getConnection();
            List<Customer> customerList = dao.getAllCustomers(conn);
            customerList.forEach(System.out::println);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(conn,null);
        }
    }

    @Test
    public void getCount() {
        Connection conn = null;
        try {
            conn = JDBCUtil.getConnection();
            System.out.println(dao.getCount(conn));
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(conn,null);
        }
    }

    @Test
    public void getMaxBirth() {
        Connection conn = null;
        try {
        
            conn = JDBCUtil.getConnection();
            System.out.println(dao.getMaxBirth(conn));
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.closeResource(conn,null);
        }
    }
}

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

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

相关文章

《实战:如何搭建一个完整的 Vue2.0 项目》- 7、Vue2.x 项目 webpack 4 升级 5(半自动升级)

1.自动升级 先全局安装升级插件 npm i npm-check npm-check-updates -g检查依赖 npm-check更新检查后的依赖并展示版本号&#xff0c;此时 package.json还没有更新 npm-check-updates升级 package.json&#xff0c;下图显示更新版本&#xff0c;此时 package.json文件已变更…

客服管理者如何调动客服人员的积极性?

客户是企业的财富&#xff0c;良好的客户服务体验可以有效地促进企业的销售和声誉&#xff0c;因此&#xff0c;客服工作显得尤为重要。而客服人员的积极性直接影响了整个客服部门的质量和效率。如何调动客服人员的积极性&#xff0c;成为了每个客服管理者都需要面对的难题。本…

Mendix 创客访谈录|质量部门开发应用程序自主可控

本期创客 我们是来自于西门子成都工厂质量部的 Mendix “草台班子” 创客访谈 在使用Mendix低代码平台开发应用软件前&#xff0c;你和你的部门/团队主要应用什么开发工具&#xff1f; 我们质量部属于OT&#xff08;运营技术&#xff09;部门, 一般是使用一些IT团队提供的功能单…

Mongoose 开源库--Filesystem(文件系统)使用笔记

一、相关API Mongoose 开源库中也包含 文件系统 相关的 API&#xff0c;如下&#xff1a; 文件虚拟层&#xff1a; struct mg_fs {int (*st)(const char *path, size_t *size, time_t *mtime); // stat filevoid (*ls)(const char *path, void (*fn)(const char *, void *), v…

结合选择MES管理系统供应商的关键因素进行深入探讨

在现代化的制造业中&#xff0c;MES管理系统已经成为了提高生产效率、降低成本、增强产品质量的重要工具。然而&#xff0c;选择一个合适的MES管理系统系统供应商并不是一件轻而易举的事。它需要对多个因素进行深入的权衡和考虑。结合上述的关键挑选因素&#xff0c;我们进一步…

C++二叉搜索树BinarySearchTree

一、介绍 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 1.若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 2.若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 3.它的左右…

C#,数值计算——积分方程与逆理论,构造n点等间隔求积的权重的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// 构造n点等间隔求积的权重 /// Constructs weights for the n-point equal-interval quadrature /// from O to(n-1)h of a function f(x) times an arbitrary /// (pos…

Parasoft C/C++test:汽车网络安全ISO 21434最佳实践

为什么汽车网络安全很重要Why Automotive Cybersecurity Is Important 许多汽车公司向电子道路车辆的转变从根本上改变了整个行业&#xff0c;提高了汽车的互联性和智能性。随着电子汽车变得更加互联和智能&#xff0c;它们也越来越依赖软件来实现车辆操作&#xff0c;驱动更多…

Netty实战专栏 | JavaIO演进之路

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Netty实战专栏 ✨特色专栏&#xff1a…

性能优于BERT的FLAIR:一篇文章入门Flair模型

文章目录 What is FLAIR&#xff1f;FLAIR ModelContextual String Embedding for Sequence Labelingexample FLAIR Application AreaSentiment AnalysisNamed Entity RecognitionText Classification FLAIR一、什么是FLAIR&#xff1f;二、FLAIR Library的优势是什么&#xff…

Linux flock和fcntl函数详解

文章目录 flock函数描述返回值和错误码笔记 fcntl函数描述复制文件描述符文件描述标志文件状态标志 咨询锁强制锁管理信号租赁文件和目录变更通知改变管道容量 返回值错误备注遗留问题 flock函数 主要功能是在已打开的文件应用或者删除共享锁或者独占锁。sys/file.h声明了这个…

时间序列聚类的直观方法

一、介绍 我们将使用轮廓分数和一些距离度量来执行时间序列聚类实验&#xff0c;同时利用直观的可视化&#xff0c;让我们看看下面的时间序列&#xff1a; 这些可以被视为具有正弦、余弦、方波和锯齿波的四种不同的周期性时间序列 如果我们添加随机噪声和距原点的距离来沿 y 轴…

苹果加大对印度的扶持,提高在其生产iphone的比重

KlipC报道&#xff1a;跟踪苹果产业链&#xff0c;有分析师预计2023年全球约12%-14%的iphone在印度生产&#xff0c;预计2024年&#xff0c;印度将生产20%-25%的iphone。 KlipC的合伙人Andi D表示&#xff1a;“近年来随着苹果对中国的以来&#xff0c;印度已经成为高科技制造和…

Netty实战专栏 | BIO详解

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Netty实战专栏 ✨特色专栏&#xff1a…

ESP32 for Arduino 分区信息

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-11-04❤️❤️ 本篇更新记录 2023-11-04❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64f;…

“线性函数”和“非线性函数”是什么?

总是会把“线性函数”和“非线性函数”与“连续的数据类型”与“非连续的数据类型”混淆&#xff0c;特此记录 一、线性函数&#xff1a; 一个函数 f 是线性的&#xff0c;如果对于任何两个输入 x1​ 和 x2​ 和任何两个常数 a 和 b&#xff0c;下列等式成立&#xff1a; 例如…

BIOS开发笔记 - HDA Audio

在PC中,音频输出是一个重要的功能之一,目前大多数采用的是英特尔高清晰音效(英语:Intel High Definition Audio,简称为HD Audio或IHD)方案,它是由Intel于2004年所提出的音效技术,能够展现高清晰度的音质效果,且能进行多声道的播放,在音质(音效质量)上超越过去的其他…

Ubuntu18.04 下PCL的卸载与安装

目录 一、卸载有问题的PCL1.7 二、编译&&安装PCL1.8.1 2.1、安装PCL依赖 2.2、编译VTK 2.3、编译PCL源码 三、 总结 写这篇博客时&#xff0c;本文方法已经在笔记本Ubuntu和VM虚拟机成功安装PCL1.8.1&#xff0c;并且通过测试。 下文方法同样适用于ubuntu18.04。…

JsonPath 数据快速查找和提取工具

常用语法 表达式说明$表示根元素$.key选择根元素下的指定键名的值$.*选择根元素下的所有属性值$.array[*]选择根元素中的数组的所有元素$.key[subkey]选择根元素中的键名为key&#xff0c;子键名为subkey的值$.key[*].subkey选择根元素中的键名为key的所有元素的子键名为subke…