当前位置:   article > 正文

Java-数据库连接池_java数据库连接池

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. <!-- 驱动类 -->
  4. <property name="driverClass">com.mysql.jdbc.Driver</property>
  5. <!-- url -->
  6. <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/pero_db01</property>
  7. <!-- 用户名 -->
  8. <property name="user">root</property>
  9. <!-- 密码 -->
  10. <property name="password">pero</property>
  11. <!-- 每次增长的连接数 -->
  12. <property name="acquireIncrement">5</property>
  13. <!-- 初始连接数 -->
  14. <property name="initialPoolSize">10</property>
  15. <!-- 最小连接数 -->
  16. <property name="minPoolSize">5</property>
  17. <!-- 最大连接数 -->
  18. <property name="maxPoolSize">50</property>
  19. <!-- 可连接的最多的命令对象数 -->
  20. <property name="maxStatements">5</property>
  21. <!-- 每个连接对象可连接的最多的命令对象数 -->
  22. <property name="maxStatementsPerConnection">2</property>
  23. </named-config>
  24. </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<Admins> 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再存到一个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<Admins> 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> T query(Connection conn/*连接对象*/, boolean closeConn/*是否关闭连接*/, String sql/*sql命令*/, ResultSetHandler<T> 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<T> { //指定具体类型
  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. * <end>
  42. * @Param: [sql, clazz, parameters]
  43. * @Return: java.util.List<T>
  44. * @Author: pero
  45. * @Date: 2022/11/5 20:27
  46. */
  47. public List<T> queryMultiply(String sql, Class<T> clazz, Object... parameters){
  48. try {
  49. connection = JDBCUtilsByDruid.getConnection();
  50. return queryRunner.query(connection, sql, new BeanListHandler<T>(clazz), parameters);
  51. } catch (SQLException e) {
  52. throw new RuntimeException(e);
  53. } finally {
  54. JDBCUtilsByDruid.close(null,null,connection);
  55. }
  56. }
  57. /*
  58. * 功能描述: <查询单行结果>
  59. * <end>
  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<T> clazz, Object...parameters){
  66. try {
  67. connection = JDBCUtilsByDruid.getConnection();
  68. return queryRunner.query(connection, sql, new BeanHandler<T>(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<Actor>{
  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<Actor> 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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/847933
推荐阅读
相关标签
  

闽ICP备14008679号