• Java编程学习-数据库连接池


    传统连接获取Connection存在的问题

    1)传统的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接都需要将Connection加载到内存中,再验证IP地址、用户名和密码,频繁的进行数据库连接操作将占用非常多的系统资源,容易造成服务器崩溃;

    2)数据库连接使用完后都必须断开连接释放资源,如果程序出现异常而未能关闭,将导致数据库内存泄漏,最终导致重启数据库;

    3)传统获取连接的方式 不能控制创建的连接数量,如果连接过多也可能导致内存泄漏致使MySQL数据库崩溃;

    4)解决传统开发中的数据库连接问题可以采用数据库连接池技术(connection pool)。

     数据库连接池基本介绍

    1)预先在缓冲池中放入一定数量的链接,当需要建立数据库连接时,只需要从“缓冲池”中取出,使用完毕后再“放回”;

    2)数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立;

    3)当应用程序向连接池请求的连接数量超过最大连接数量时,这些请求将被加入到等待队列中。

    通过连接池链接数据库步骤

    1)从连接池取出连接;

    2)使用链接,操作SQL语句;

    3)连接放回连接池(程序对连接的引用断开,连接依然可以重复使用)。

    如果当前连接都被占用,则新的待连接程序进入等待队列。

    数据库连接池种类

    1)JDBC的数据库连接池使用 javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现;

    2)C3P0数据库连接池,速度相对较慢但是稳定性比较好(hibernate,spring都采用该连接池);

    3)DBCP数据库连接池,速度相对C3P0较快,但稳定性较差;

    4)Proxool数据库连接池,有监控链接池状态的功能,稳定性相对于C3P0差一些;

    5)BoneCP数据库连接池,速度快;

    6)Druid(德鲁伊)是Alibaba提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池。

    C3P0测试代码

    1. package com.pero.datasource;
    2. import com.mchange.v2.c3p0.ComboPooledDataSource;
    3. import org.junit.Test;
    4. import java.beans.PropertyVetoException;
    5. import java.io.FileInputStream;
    6. import java.io.FileNotFoundException;
    7. import java.io.IOException;
    8. import java.sql.Connection;
    9. import java.sql.SQLException;
    10. import java.util.Properties;
    11. /**
    12. * @author Pero
    13. * @version 1.0
    14. * @title: C3P0_
    15. * @date 2022/10/28 22:48
    16. */
    17. public class C3P0_ {
    18. //使用方法一:在程序中指定相关参数(user、url、password)
    19. @Test
    20. public void testC3P0_01() throws IOException, PropertyVetoException, SQLException {
    21. //1.创建数据源对象
    22. ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
    23. //2.通过配置文件mysql.properties获取相关信息
    24. Properties properties = new Properties();
    25. properties.load(new FileInputStream("src\\mysql.properties"));
    26. //3.获取相关属性
    27. String user = properties.getProperty("user");
    28. String password = properties.getProperty("password");
    29. String url = properties.getProperty("url");
    30. String driver = properties.getProperty("driver");
    31. //4.给数据源comboPooledDataSource设置相关参数(连接管理交给数据源comboPooledDataSource)
    32. comboPooledDataSource.setDriverClass(driver); //设置连接数据库驱动
    33. comboPooledDataSource.setJdbcUrl(url);
    34. comboPooledDataSource.setUser(user);
    35. comboPooledDataSource.setPassword(password);
    36. //5.设置初始化连接数和连接数上限
    37. comboPooledDataSource.setInitialPoolSize(10); //初始化连接数
    38. comboPooledDataSource.setMaxPoolSize(50); //连接数上线
    39. //6.获取链接
    40. long start = System.currentTimeMillis();
    41. for (int i = 0; i < 5000; i++) {
    42. Connection connection = comboPooledDataSource.getConnection();
    43. connection.close();
    44. }
    45. long end = System.currentTimeMillis();
    46. System.out.println("连接数据库5000次用时:" + (end - start));
    47. }
    48. //使用方法二:使用配置文件模板来完成
    49. @Test
    50. public void testC3P0_02() throws SQLException {
    51. //1.先导入c3p0-config.xml文件src目录下
    52. //2.该文件指定了连接数据库和连接池的相关参数
    53. ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("myc3p0");
    54. long start = System.currentTimeMillis();
    55. for (int i = 0; i < 5000; i++) {
    56. Connection connection = comboPooledDataSource.getConnection();
    57. connection.close();
    58. }
    59. long end = System.currentTimeMillis();
    60. System.out.println("连接数据库5000次耗时:" + (end - start));
    61. }
    62. }
    1. <c3p0-config>
    2. <named-config name="myc3p0">
    3. <property name="driverClass">com.mysql.jdbc.Driverproperty>
    4. <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/pero_db01property>
    5. <property name="user">rootproperty>
    6. <property name="password">peroproperty>
    7. <property name="acquireIncrement">5property>
    8. <property name="initialPoolSize">10property>
    9. <property name="minPoolSize">5property>
    10. <property name="maxPoolSize">50property>
    11. <property name="maxStatements">5property>
    12. <property name="maxStatementsPerConnection">2property>
    13. named-config>
    14. c3p0-config>

    Druid测试代码

    1. package com.pero.datasource;
    2. import com.alibaba.druid.pool.DruidDataSourceFactory;
    3. import org.junit.Test;
    4. import org.junit.jupiter.api.TestInstance;
    5. import javax.sql.DataSource;
    6. import java.io.FileInputStream;
    7. import java.io.FileNotFoundException;
    8. import java.io.FileReader;
    9. import java.io.IOException;
    10. import java.sql.Connection;
    11. import java.util.Properties;
    12. /**
    13. * @author Pero
    14. * @version 1.0
    15. * @title: Druid_
    16. * @date 2022/10/28 22:57
    17. */
    18. public class Druid_ {
    19. //添加Druid的jar包和相关配置文件
    20. @Test
    21. public void testDruid() throws Exception {
    22. //创建properties对象,读取配置文件
    23. Properties properties = new Properties();
    24. properties.load(new FileInputStream("src\\druid.properties"));
    25. //创建指定参数的数据库连接池(德鲁伊连接池)
    26. DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
    27. long start = System.currentTimeMillis();
    28. //建立连接
    29. for (int i = 0; i < 5000; i++) {
    30. Connection connection = dataSource.getConnection();
    31. connection.close();
    32. }
    33. long end = System.currentTimeMillis();
    34. System.out.println("数据库连接耗时:" + (end - start));
    35. }
    36. }
    1. #key=value
    2. driverClassName=com.mysql.jdbc.Driver
    3. url=jdbc:mysql://localhost:3306/pero_db01?rewriteBatchedStatements=true
    4. #url=jdbc:mysql://127.0.0.1:3306/pero_db01
    5. username=root
    6. password=pero
    7. #initial connection size
    8. initialSize=10
    9. #min idle connection size
    10. minIdle=5
    11. #max active connection size
    12. maxActive=20
    13. #max wait time (5000 mil seconds)
    14. maxWait=5000

    德鲁伊工具类

    1. package com.pero.datasource;
    2. import com.alibaba.druid.pool.DruidDataSourceFactory;
    3. import com.mysql.jdbc.ResultSetRow;
    4. import com.sun.corba.se.spi.ior.IdentifiableFactory;
    5. import javax.sql.DataSource;
    6. import java.io.FileInputStream;
    7. import java.io.IOException;
    8. import java.sql.Connection;
    9. import java.sql.ResultSet;
    10. import java.sql.SQLException;
    11. import java.sql.Statement;
    12. import java.util.Properties;
    13. /**
    14. * @author Pero
    15. * @version 1.0
    16. * @title: JDBCUtilsByDruid
    17. * @date 2022/10/29 22:33
    18. */
    19. public class JDBCUtilsByDruid {
    20. private static DataSource ds;
    21. //在静态代码块中对ds初始化
    22. static {
    23. Properties properties = new Properties();
    24. try {
    25. properties.load(new FileInputStream("src\\druid.properties"));
    26. ds = DruidDataSourceFactory.createDataSource(properties);
    27. } catch (Exception e) {
    28. throw new RuntimeException(e);
    29. }
    30. }
    31. //获取connection
    32. public static Connection getConnection() throws SQLException {
    33. return ds.getConnection();
    34. }
    35. //关闭资源,将连接放回连接池
    36. public void close(ResultSet resultSet, Statement statement, Connection connection){
    37. try {
    38. if (resultSet != null){
    39. resultSet.close();
    40. }
    41. if (statement != null){
    42. statement.close();
    43. }
    44. if (connection != null){
    45. connection.close();
    46. }
    47. } catch (SQLException e) {
    48. throw new RuntimeException(e);
    49. }
    50. }
    51. }

    测试代码

    1. package com.pero.datasource;
    2. import org.junit.Test;
    3. import java.sql.Connection;
    4. import java.sql.PreparedStatement;
    5. import java.sql.ResultSet;
    6. import java.sql.SQLException;
    7. import java.util.Properties;
    8. /**
    9. * @author Pero
    10. * @version 1.0
    11. * @title: JDBCUtilsByDruid_Use
    12. * @date 2022/10/29 23:30
    13. */
    14. public class JDBCUtilsByDruid_Use {
    15. @Test
    16. public void testUseDruid(){
    17. Connection connection = null;
    18. PreparedStatement preparedStatement = null;
    19. ResultSet resultSet = null;
    20. String sql = "insert into admin values (?,?)";
    21. try {
    22. connection = JDBCUtilsByDruid.getConnection(); //com.alibaba.druid.pool.DruidPooledConnection
    23. preparedStatement = connection.prepareStatement(sql);
    24. preparedStatement.setString(1,"pero");
    25. preparedStatement.setInt(2,951357);
    26. preparedStatement.executeUpdate();
    27. } catch (SQLException e) {
    28. throw new RuntimeException(e);
    29. } finally {
    30. JDBCUtilsByDruid.close(null,preparedStatement,connection);
    31. }
    32. }
    33. @Test
    34. public void testSelect(){
    35. Connection connection = null;
    36. PreparedStatement preparedStatement = null;
    37. ResultSet resultSet = null;
    38. String sql = "select * from admin";
    39. try {
    40. connection = JDBCUtilsByDruid.getConnection();
    41. preparedStatement = connection.prepareStatement(sql);
    42. resultSet = preparedStatement.executeQuery();
    43. while(resultSet.next()){
    44. String name = resultSet.getString("name");
    45. int password = resultSet.getInt("password");
    46. System.out.println(name + "\t" + password);
    47. }
    48. } catch (SQLException e) {
    49. throw new RuntimeException(e);
    50. } finally {
    51. JDBCUtilsByDruid.close(resultSet,preparedStatement,connection);
    52. }
    53. }
    54. }

    Apache-DBUtils

    问题分析

    1)关闭connection后,resultSet结果集无法使用;

    2)resultSet不利于数据管理

    3)示意图

    MySQL数据库

    java程序

    1.得到链接

    2.发送SQL指令

    意义:

    相当于将表中的数据信息与ArrayList集合相对应的保存

    返回resultSet

    存在问题

    1.结果集和connection是关联的,如果关闭连接则不能再使用结果集;

    2.结果集不利于数据管理【只能使用一次】;

    3.使用返回信息不方便。

    将结果集记录,封装到ArrayList<数据表类名>
    数据表信息

    Java类==>(JavaBean,PoJO,Domain)

    class Test {

            //属性

            private int id;

            private String name;

            ...

            //无参构造器

            //带参构造器

            //Getter And Setter

    }

    一个表数据对象对应一条表记录,表对象放入到ArrayList集合

    方法演示测试代码

    1. package com.pero.datasource;
    2. import org.junit.Test;
    3. import java.sql.Connection;
    4. import java.sql.PreparedStatement;
    5. import java.sql.ResultSet;
    6. import java.sql.SQLException;
    7. import java.util.ArrayList;
    8. import java.util.Properties;
    9. /**
    10. * @author Pero
    11. * @version 1.0
    12. * @title: JDBCUtilsByDruid_Use
    13. * @date 2022/10/29 23:30
    14. */
    15. public class JDBCUtilsByDruid_Use {
    16. //将ResultSet封装到ArrayList集合中
    17. @Test
    18. public void testSelectToArrayList() {
    19. Connection connection = null;
    20. PreparedStatement preparedStatement = null;
    21. ResultSet resultSet = null;
    22. String sql = "select * from admins";
    23. ArrayList adminsArrayList = new ArrayList<>();
    24. try {
    25. connection = JDBCUtilsByDruid.getConnection();
    26. preparedStatement = connection.prepareStatement(sql);
    27. resultSet = preparedStatement.executeQuery();
    28. while (resultSet.next()) {
    29. int id = resultSet.getInt("id");
    30. String user_name = resultSet.getString("user_name");
    31. String password = resultSet.getString("password");
    32. //把得到的resultSet信息封装到Admins对象,然后放入到ArrayList集合中
    33. Admins admins = new Admins(id, user_name, password);
    34. adminsArrayList.add(admins);
    35. }
    36. for (Admins admins : adminsArrayList) {
    37. System.out.println(admins.getId() + "\t" + admins.getName() +
    38. "\t" + admins.getPassword());
    39. }
    40. } catch (SQLException e) {
    41. throw new RuntimeException(e);
    42. } finally {
    43. JDBCUtilsByDruid.close(resultSet,preparedStatement,connection);
    44. }
    45. //因为ArrayList与connection没有任何关联,该集合可以复用
    46. //return list;
    47. }
    48. }
    1. package com.pero.datasource;
    2. /**
    3. * @author Pero
    4. * @version 1.0
    5. * @title: Admins
    6. * @date 2022/10/30 22:02
    7. */
    8. public class Admins {
    9. private Integer id;
    10. private String user_name;
    11. private String password;
    12. public Admins() { //一定要给一个无参构造器【反射需要】
    13. }
    14. public Admins(Integer id, String user_name, String password) {
    15. this.id = id;
    16. this.user_name = user_name;
    17. this.password = password;
    18. }
    19. public Integer getId() {
    20. return id;
    21. }
    22. public void setId(Integer id) {
    23. this.id = id;
    24. }
    25. public String getName() {
    26. return user_name;
    27. }
    28. public void setName(String user_name) {
    29. this.user_name = user_name;
    30. }
    31. public String getPassword() {
    32. return password;
    33. }
    34. public void setPassword(String password) {
    35. this.password = password;
    36. }
    37. @Override
    38. public String toString() {
    39. return "Admins{" +
    40. "id=" + id +
    41. ", user_name='" + user_name + '\'' +
    42. ", password='" + password + '\'' +
    43. '}';
    44. }
    45. }

    Apache-DBUtils基本介绍

    1)commons-dbutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量;

    DbUtils类

    1)QueryRunner类:该类封装了SQL的的执行,并且是线程安全的,可实现增删改查、批处理;

    2)使用QueryRunner类实现查询;

    3)ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按照要求转换为另一种形式。

    ArrayHandler:把结果集中的第一行数据转换成对象数组;
    ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中;
    BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中;
    BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List中;
    ColumnListHandler:将结果集中某一列的数据存放到List中;
    KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List),再把这些map再存到一个map里,其key为指定的列;
    MapHandler:

    将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值;

    MapListHandler:将结果集中的每一行数据都封装到一个Map中,然后再存放到List中;
    ScalarHandler:获取结果集中第一行数据指定列的值,常用来进行单值查询。

    测试代码1

    1. package com.pero.datasource;
    2. import org.apache.commons.dbutils.QueryRunner;
    3. import org.apache.commons.dbutils.handlers.BeanHandler;
    4. import org.apache.commons.dbutils.handlers.BeanListHandler;
    5. import org.apache.commons.dbutils.handlers.ScalarHandler;
    6. import org.junit.Test;
    7. import java.sql.Connection;
    8. import java.sql.SQLException;
    9. import java.util.List;
    10. /**
    11. * @author Pero
    12. * @version 1.0
    13. * @title: DBUtils_USE
    14. * @date 2022/10/31 16:52
    15. */
    16. public class DBUtils_USE {
    17. //使用apache-DBUtils 工具类 + druid完成对表的crud操作
    18. @Test
    19. //使用apache-dbUtils + druid查询多条语句
    20. public void testQueryMany() throws SQLException { //返回结果为多行数据
    21. //获取链接
    22. Connection connection = JDBCUtilsByDruid.getConnection();
    23. String sql = "select * from admins where id >= ?";
    24. //使用DBUtils类和接口,先引入DBUtils相关jar文件,并导入到该项目中
    25. //创建QueryRunner
    26. QueryRunner queryRunner = new QueryRunner();
    27. //使用queryRunner对象的方法返回ArrayList结果集
    28. //query()方法通过连接并执行sql语句,得到一个结果集ResultSet并封装到ArrayList集合中,并返回集合
    29. //connection:连接;
    30. // sql:执行的sql语句;
    31. //BeanListHandler查询多条语句
    32. //new BeanListHandler<>(Admins.class):将ResultSet取出存放到Admins对象中然后封装到ArrayList中
    33. //Admins.class:底层利用反射机制查看Admins类中有哪些属性,来进行封装操作;
    34. //1:该位置是可变形参,可以传入多个参数,该参数是给sql语句中的?赋值;
    35. //ResultSet和PrepareStatement会在query()方法中进行了关闭
    36. List query =
    37. queryRunner.query(connection, sql, new BeanListHandler<>(Admins.class), 1);
    38. for (Admins admins : query) {
    39. System.out.println(admins);
    40. }
    41. //释放资源
    42. JDBCUtilsByDruid.close(null,null,connection);
    43. }
    44. @Test
    45. //使用apache-dbUtils + druid查询一条语句
    46. public void testQuerySingle() throws SQLException {
    47. Connection connection = JDBCUtilsByDruid.getConnection();
    48. String sql = "select * from admins where id = ?";
    49. QueryRunner queryRunner = new QueryRunner();
    50. //查询单行记录,返回单个对象,使用的Handler是BeanHandler
    51. Admins query =
    52. queryRunner.query(connection, sql, new BeanHandler<>(Admins.class), 1);
    53. System.out.println(query);
    54. JDBCUtilsByDruid.close(null,null,connection);
    55. }
    56. //使用apache-dbUtils + druid 查询单行单列-返回一个Object对象
    57. @Test
    58. public void testScalar() throws SQLException {
    59. Connection connection = JDBCUtilsByDruid.getConnection();
    60. QueryRunner queryRunner = new QueryRunner();
    61. String sql = "select user_name from admins where id = ?";
    62. Object object = queryRunner.query(connection, sql, new ScalarHandler<>(), 3);
    63. System.out.println(object);
    64. JDBCUtilsByDruid.close(null,null,connection);
    65. }
    66. //使用apache-dbUtils + druid 完成DML(delete、insert、update)
    67. @Test
    68. public void testDML() throws SQLException {
    69. Connection connection = JDBCUtilsByDruid.getConnection();
    70. QueryRunner queryRunner = new QueryRunner();
    71. String sql_update = "update admins set password = ? where user_name = ?";
    72. String sql_insert = "insert into admins values (null,?,?)";
    73. String sql_delete = "delete from admins where id = ?";
    74. //执行DML操作调用queryRunner的update()方法,返回值为受影响的行数
    75. //int affectedRow = queryRunner.update(connection, sql_update, 213546, "jack0");
    76. //int affectedRow01 = queryRunner.update(connection, sql_insert, "lucy", 123456);
    77. int affectedRow02 = queryRunner.update(connection, sql_delete, 5);
    78. //System.out.println(affectedRow > 0 ? "成功" : "执行没有影响到表");
    79. //System.out.println(affectedRow01 > 0 ? "执行成功" : "执行没有影响到表");
    80. System.out.println(affectedRow02 > 0 ? "执行成功" : "执行结果没有影响到表");
    81. JDBCUtilsByDruid.close(null,null,connection);
    82. }
    83. }

    源码分析

    1. private T query(Connection conn/*连接对象*/, boolean closeConn/*是否关闭连接*/, String sql/*sql命令*/, ResultSetHandler rsh/*结果集的对象的集合*/, Object... params/*sql命令中对应?位置的值*/) throws SQLException {
    2. if (conn == null) { //判断传入的连接对象是否为null,如果为null抛出Null connection连接异常
    3. throw new SQLException("Null connection");
    4. } else if (sql == null) { //判断语句是否为空,如果为空则进行下一组判断
    5. if (closeConn) { //判断closeConn是否为true,如果为true则关闭连接
    6. this.close(conn);
    7. }
    8. throw new SQLException("Null SQL statement"); //抛出Null SQL statement异常
    9. } else if (rsh == null) { //判断接收的集合对象是否为null
    10. if (closeConn) { //判断closeConn是否为true,如果为true则关闭连接
    11. this.close(conn);
    12. }
    13. throw new SQLException("Null ResultSetHandler"); //抛出Null ResultSetHandler异常
    14. } else {
    15. PreparedStatement stmt = null; //定义preparedStatement、ResultSet、T引用
    16. ResultSet rs = null;
    17. T result = null;
    18. try {
    19. stmt = this.prepareStatement(conn, sql); //将preparedStatement对象传给stmt
    20. this.fillStatement(stmt, params); //将params的值赋值给预处理对象stat中sql语句的问号
    21. rs = this.wrap(stmt.executeQuery()); //执行sql语句返回结果集,并将结果集resultSet对象经过处理后传给rs
    22. result = rsh.handle(rs); //将结果集经过处理(使用到了反射机制获取Admins类中的信息对结果集进行封装)传入rsh(ArrayList集合)并指向result引用
    23. } catch (SQLException var33) {
    24. this.rethrow(var33, sql, params); //异常抛出
    25. } finally { //资源关闭
    26. try {
    27. this.close(rs);
    28. } finally {
    29. this.close(stmt);
    30. if (closeConn) {
    31. this.close(conn);
    32. }
    33. }
    34. }
    35. return result; //返回结果
    36. }
    37. }

    数据表和JavaBean的类型映射关系

    int,double等类型在Java中都必须用包装类,因为mysql中的所有类型都可能是null,而Java中只有引用类型才有null值;

    JavaBean
    int(11)Integer
    varchar(32),char(1)String
    doubleDouble
    dateDate

    BasicDAO(date access object数据访问对象)

    apache-dbutils + Druid 虽然简化了JDBC开发,但依旧存在着不足:

    1)SQL语句是固定的,不能通过参数传入,通用性不足,进行改进以便更好执行增删改查命令;

    2)对于select操作,如果有返回值,则返回类型不能固定,需要使用泛型;

    3)对于众多的数据表和复杂的业务需求,不可能只靠一个Java类来完成;

    4)BasicDAO示意图:

    TestDAO

    1.根据业务需求使用对应的DAO;

    2.职能划分各司其职,业务设计清晰。

    调↓用

    AppView

    1.界面层;

    2.调用service层的相关类,得到结果显示数据。

    调↓用

    ActorService/GoodsService/OrderService

    1.业务层;

    2.组织sql命令,并调用相应的XxxDAO,完成综合需求。

    调↓用

    DAO

                    BasicDAO

    1.将各类DAO共同的代码归类到BasicDAO;

    2.简化代码,提高维护性和可读性。

    继↑承

    ActorDAO

    完成对actor表的增删改查操作

    可以有特有操作

    GoodsDAO

    完成对goods表的增删改查操作

    可以有特有操作

    OrderDAO

    完成对order表的增删改查操作

    可以有特有操作

    操↓作操↓作操↓作
    MySQL
    actor表goods表order表
    关↑联关↑联关↑联
    JavaBean
    Actor类  [JavaBean,domain,pojo]Goods类 [JavaBean,domain,pojo]Order类  [JavaBean,domain,pojo]

    基本介绍

    1)通用类BasicDAO是专门与数据库交互的,用以完成对数据库(表)的增删改查操作;

    2)在BasicDAO的基础上实现一张表对应一个DAO,例如Actor表-Actor.java类(JavaBean)-ActorDAO.java。

    BasicDAO应用设计

    1)创建com.pero.dao_包;

    2)在com.pero.dao_包下创建utils工具包,存放工具类;

     JDBCUtilsByDruid类

    1. package com.pero.dao_.utils;
    2. import com.alibaba.druid.pool.DruidDataSourceFactory;
    3. import javax.sql.DataSource;
    4. import java.io.FileInputStream;
    5. import java.sql.Connection;
    6. import java.sql.ResultSet;
    7. import java.sql.SQLException;
    8. import java.sql.Statement;
    9. import java.util.Properties;
    10. /**
    11. * @author Pero
    12. * @version 1.0
    13. * @title: JDBCUtilsByDruid
    14. * @date 2022/10/29 22:33
    15. */
    16. public class JDBCUtilsByDruid {
    17. private static DataSource ds;
    18. //在静态代码块中对ds初始化
    19. static {
    20. Properties properties = new Properties();
    21. try {
    22. properties.load(new FileInputStream("src\\druid.properties"));
    23. ds = DruidDataSourceFactory.createDataSource(properties);
    24. } catch (Exception e) {
    25. throw new RuntimeException(e);
    26. }
    27. }
    28. //获取connection
    29. public static Connection getConnection() throws SQLException {
    30. return ds.getConnection();
    31. }
    32. //关闭资源,将连接放回连接池
    33. public static void close(ResultSet resultSet, Statement statement, Connection connection){
    34. try {
    35. if (resultSet != null){
    36. resultSet.close();
    37. }
    38. if (statement != null){
    39. statement.close();
    40. }
    41. if (connection != null){
    42. connection.close();
    43. }
    44. } catch (SQLException e) {
    45. throw new RuntimeException(e);
    46. }
    47. }
    48. }

    3)在com.pero.dao_包下创建domain包,存放JavaBean文件;

    Actor类

    1. package com.pero.dao_.domain;
    2. import java.util.Date;
    3. /**
    4. * @author Pero
    5. * @version 1.0
    6. * @title: Actor
    7. * @date 2022/11/5 17:25
    8. */
    9. public class Actor {
    10. /**
    11. * 数据库中actor表的列属性
    12. */
    13. private Integer id;
    14. private String name;
    15. private String sex;
    16. private Date date;
    17. private Integer phone;
    18. /**
    19. * 空构造器,方便反射使用
    20. */
    21. public Actor() {
    22. }
    23. /**
    24. * 全属性构造器
    25. */
    26. public Actor(Integer id, String name, String sex, Date date, Integer phone) {
    27. this.id = id;
    28. this.name = name;
    29. this.sex = sex;
    30. this.date = date;
    31. this.phone = phone;
    32. }
    33. /**
    34. * Setter and Getter
    35. */
    36. public Integer getId() {
    37. return id;
    38. }
    39. public void setId(Integer id) {
    40. this.id = id;
    41. }
    42. public String getName() {
    43. return name;
    44. }
    45. public void setName(String name) {
    46. this.name = name;
    47. }
    48. public String getSex() {
    49. return sex;
    50. }
    51. public void setSex(String sex) {
    52. this.sex = sex;
    53. }
    54. public Date getDate() {
    55. return date;
    56. }
    57. public void setDate(Date date) {
    58. this.date = date;
    59. }
    60. public Integer getPhone() {
    61. return phone;
    62. }
    63. public void setPhone(Integer phone) {
    64. this.phone = phone;
    65. }
    66. /**
    67. * toString
    68. */
    69. @Override
    70. public String toString() {
    71. return "Actor{" +
    72. "id=" + id +
    73. ", name='" + name + '\'' +
    74. ", sex='" + sex + '\'' +
    75. ", date=" + date +
    76. ", phone=" + phone +
    77. '}';
    78. }
    79. }

    4)在com.pero.dao_包下创建dao包,存放XxxDAO和BasicDAO类;

    BasicDAO类

    1. package com.pero.dao_.dao;
    2. import com.pero.datasource.JDBCUtilsByDruid;
    3. import org.apache.commons.dbutils.QueryRunner;
    4. import org.apache.commons.dbutils.handlers.BeanHandler;
    5. import org.apache.commons.dbutils.handlers.BeanListHandler;
    6. import org.apache.commons.dbutils.handlers.ScalarHandler;
    7. import javax.lang.model.element.VariableElement;
    8. import java.sql.Connection;
    9. import java.sql.SQLException;
    10. import java.util.List;
    11. /**
    12. * @author Pero
    13. * @version 1.0
    14. * @title: BasicDAO
    15. * @date 2022/11/5 17:48
    16. */
    17. public class BasicDAO { //指定具体类型
    18. private QueryRunner queryRunner = new QueryRunner();
    19. Connection connection = null;
    20. /*
    21. * 功能描述: <增删改操作>
    22. * <>
    23. * @Param: [sql,parameters]
    24. * @Return: int
    25. * @Author: pero
    26. * @Date: 2022/11/6 12:41
    27. */
    28. public int update(String sql, Object...parameters){
    29. try {
    30. connection = JDBCUtilsByDruid.getConnection();
    31. int update = queryRunner.update(connection,sql, parameters);
    32. return update;
    33. } catch (SQLException e) {
    34. throw new RuntimeException(e);
    35. } finally {
    36. JDBCUtilsByDruid.close(null,null,connection);
    37. }
    38. }
    39. /*
    40. * 功能描述: <返回多个对象(多行查询结果),针对任意表>
    41. *
    42. * @Param: [sql, clazz, parameters]
    43. * @Return: java.util.List
    44. * @Author: pero
    45. * @Date: 2022/11/5 20:27
    46. */
    47. public List queryMultiply(String sql, Class clazz, Object... parameters){
    48. try {
    49. connection = JDBCUtilsByDruid.getConnection();
    50. return queryRunner.query(connection, sql, new BeanListHandler(clazz), parameters);
    51. } catch (SQLException e) {
    52. throw new RuntimeException(e);
    53. } finally {
    54. JDBCUtilsByDruid.close(null,null,connection);
    55. }
    56. }
    57. /*
    58. * 功能描述: <查询单行结果>
    59. *
    60. * @Param: [sql, clazz, parameters]
    61. * @Return: T
    62. * @Author: pero
    63. * @Date: 2022/11/5 20:45
    64. */
    65. public T querySingle(String sql, Class clazz, Object...parameters){
    66. try {
    67. connection = JDBCUtilsByDruid.getConnection();
    68. return queryRunner.query(connection, sql, new BeanHandler(clazz), parameters);
    69. } catch (SQLException e) {
    70. throw new RuntimeException(e);
    71. } finally {
    72. JDBCUtilsByDruid.close(null,null,connection);
    73. }
    74. }
    75. /*
    76. * 功能描述: <查询单行单列的方法,返回单值>
    77. * <>
    78. * @Param: [sql,parameters]
    79. * @Return: [Object]
    80. * @Author: pero
    81. * @Date: 2022/11/5 20:58
    82. */
    83. public Object queryScalar(String sql, Object...parameters){
    84. try {
    85. connection = JDBCUtilsByDruid.getConnection();
    86. return queryRunner.query(connection,sql, new ScalarHandler(), parameters);
    87. } catch (SQLException e) {
    88. throw new RuntimeException(e);
    89. } finally {
    90. JDBCUtilsByDruid.close(null,null,connection);
    91. }
    92. }
    93. }

     ActorDAO类

    1. package com.pero.dao_.dao;
    2. import com.pero.dao_.domain.Actor;
    3. /**
    4. * @author Pero
    5. * @version 1.0
    6. * @title: ActorDAO
    7. * @date 2022/11/6 12:53
    8. */
    9. public class ActorDAO extends BasicDAO{
    10. //具有BasicDAO所有的方法
    11. //根据业务需求编写特有方法
    12. }

    5)在com.pero.dao_包下创建test包,存放测试类。

    1. package com.pero.dao_.test;
    2. import com.pero.dao_.dao.ActorDAO;
    3. import com.pero.dao_.domain.Actor;
    4. import org.apache.commons.dbutils.QueryRunner;
    5. import org.junit.Test;
    6. import java.io.FileInputStream;
    7. import java.io.FileNotFoundException;
    8. import java.io.FileReader;
    9. import java.io.IOException;
    10. import java.util.List;
    11. import java.util.Properties;
    12. /**
    13. * @author Pero
    14. * @version 1.0
    15. * @title: TestDAO
    16. * @date 2022/11/6 12:55
    17. */
    18. public class TestDAO {
    19. //测试actor表的增删改查操作
    20. @Test
    21. /*
    22. * 功能描述: <多行查询>
    23. * <>
    24. * @Param: []
    25. * @Return: void
    26. * @Author: pero
    27. * @Date: 2022/11/6 14:18
    28. */
    29. public void testActorSelectForMultiply(){
    30. ActorDAO actorDAO = new ActorDAO();
    31. List actors =
    32. actorDAO.queryMultiply("select * from actor where id > ?", Actor.class, 3);
    33. for (Actor actor : actors) {
    34. System.out.println(actor);
    35. }
    36. }
    37. @Test
    38. /*
    39. * 功能描述: <单行查询>
    40. * <>
    41. * @Param: []
    42. * @Return: void
    43. * @Author: pero
    44. * @Date: 2022/11/6 14:26
    45. */
    46. public void testActorSelectForSingle(){
    47. ActorDAO actorDAO = new ActorDAO();
    48. Actor actor =
    49. actorDAO.querySingle("select * from actor where id = ?", Actor.class, 5);
    50. System.out.println(actor);
    51. }
    52. @Test
    53. /*
    54. * 功能描述: <单行单列查询>
    55. * <>
    56. * @Param: []
    57. * @Return: void
    58. * @Author: pero
    59. * @Date: 2022/11/6 14:32
    60. */
    61. public void testActorSelectForScalar(){
    62. ActorDAO actorDAO = new ActorDAO();
    63. Object scalar =
    64. actorDAO.queryScalar("select name from actor where id = ?", 4);
    65. System.out.println(scalar);
    66. }
    67. @Test
    68. /*
    69. * 功能描述: <添加数据>
    70. * <>
    71. * @Param: []
    72. * @Return: void
    73. * @Author: pero
    74. * @Date: 2022/11/6 18:16
    75. */
    76. public void testActorInsertForUpdate() throws IOException {
    77. ActorDAO actorDAO = new ActorDAO();
    78. Properties properties = new Properties();
    79. properties.load(new FileInputStream("src\\actorFile.properties"));
    80. String name = properties.getProperty("name");
    81. String sex = properties.getProperty("sex");
    82. String borndate = properties.getProperty("borndate");
    83. String phone = properties.getProperty("phone");
    84. int update =
    85. actorDAO.update("insert into actor values (null,?,?,?,?)",name,sex,borndate,phone);
    86. System.out.println(update > 0 ? "数据添加成功" : "添加操作未对数据库表产生影响");
    87. }
    88. @Test
    89. /*
    90. * 功能描述: <修改数据>
    91. * <>
    92. * @Param: []
    93. * @Return: void
    94. * @Author: pero
    95. * @Date: 2022/11/6 18:57
    96. */
    97. public void testActorUpdateForUpdate() throws IOException {
    98. ActorDAO actorDAO = new ActorDAO();
    99. Properties properties = new Properties();
    100. properties.load(new FileInputStream("src\\actorFile.properties"));
    101. String name = properties.getProperty("name");
    102. String sex = properties.getProperty("sex");
    103. String borndate = properties.getProperty("borndate");
    104. String phone = properties.getProperty("phone");
    105. int update =
    106. actorDAO.update("update actor set name = ?, sex = ?, borndate = ?, phone = ? where id = ?", name, sex, borndate, phone, 5);
    107. System.out.println(update > 0 ? "修改成功" : "操作语句未对表产生影响");
    108. }
    109. @Test
    110. /*
    111. * 功能描述: <删除指定行数据>
    112. * <>
    113. * @Param: []
    114. * @Return: void
    115. * @Author: pero
    116. * @Date: 2022/11/6 19:03
    117. */
    118. public void testActorDeleteForUpdate(){
    119. ActorDAO actorDAO = new ActorDAO();
    120. int update =
    121. actorDAO.update("delete from actor where id = ?", 6);
    122. System.out.println(update > 0 ? "删除成功" : "操作语句未对表产生影响");
    123. }
    124. }

    actorFile.properties

    1. name=marry
    2. sex=woman
    3. borndate=2002-05-31
    4. phone=136656326

  • 相关阅读:
    浅拷贝和深拷贝
    Pohlig-Hellman算法解决DLP问题
    麻雀算法(SSA)优化混合核极限学习机(HKELM)分类预测,多输入单输出模型,SSA-HKELM分类预测。
    docker命令总结
    2024050401-重学 Java 设计模式《实战代理模式》
    【Elasticsearch<一>✈️✈️】简单安装使用以及各种踩坑
    IDEA自定义Maven仓库
    FPGA项目开发之同步信号和亚稳态
    韩语学习|韩语零基础|柯桥韩语学校,每日一词
    申诉解决TeamViewer免费个人版被误判为商业使用
  • 原文地址:https://blog.csdn.net/Ego_Ekko/article/details/127576664