之前在学校的Java及Web课上只教了通过Jdbc来与数据库连接并对数据库进行操作,这一过程是很繁琐的,每次操作都要使用大段的模板代码。为了使开发更加简洁高效,也就有了像数据库连接池,DBUtils这种对连接中的某一步骤进行简化,再到后来的MyBatis框架对持久层的操作进行再一次的封装简化。这也让我想起了曾经刚接触Java时,懵懂无知,一位前辈告诉我Java学到后面会学到各种框架,开发只会越来越简便。现在看来确实如此,Java的发展更新正是很多前辈站在巨人的肩膀上,不断优化丰富,衍生出了现在丰富的Java生态。

为什么要用数据库连接池

传统的JDBC开发可分为以下5步:

  1. 加载驱动
  2. 获取连接
  3. 通过Statement执行sql语句
  4. 将结果通过resultSet接收
  5. 断开连接

通过以上步骤,每一次对数据库进行操作都要先建立连接,然后断开,很浪费资源,于是便有了数据库连接池的概念:
数据库连接池的基本思想就是为数据库建⽴⼀个缓冲池,预先向缓冲池中放⼊⼀定数量的连接对象,当需要获取数据库连接的时候,只需要从缓冲池中取出⼀个对象,⽤完之后再放回到缓冲池中,供下⼀次请求使⽤,做到了资源的重复利⽤,允许程序重复使⽤⼀个现有的数据库连接对象,⽽不需要重新创建。
当数据库连接池中没有空闲的连接时,新的请求就会进⼊等待队列,等待其他线程释放连接。
可以理解为对以上第二步和第五步的简化

数据库连接池的实现

JDBC 的数据库连接池使⽤ javax.sql.DataSource 接⼝来完成的,DataSource 是 Java 官⽅提供的接⼝,使⽤的时候开发者并不需要⾃⼰来实现该接⼝,可以使⽤第三⽅的⼯具,这里以C3P0为例

另外,通过 dataSource.getConnection();获得的其实是一个代理对象,这个代理对象中包含了真正的Connection inner,我们可以通过反射获得这个inner
image.png
上面表示代理类,下面表示inner的类。

代码实现:

public class DataSourceTest {
 public static void main(String[] args) {
 try {
 //创建C3P0
 ComboPooledDataSource dataSource = new ComboPooledDataSource();
 dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
 dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?
useUnicode=true&characterEncoding=UTF-8");
 dataSource.setUser("root");
 dataSource.setPassword("root");
 Connection connection = dataSource.getConnection();
 System.out.println(connection);
 //还回到数据库连接池中
 connection.close();
 } catch (PropertyVetoException e) {
 e.printStackTrace();
 } catch (SQLException e){
 e.printStackTrace();
 }
 }
}

向上面把配置直接写入代码中,每次修改配置都要重新编译生成新的字节码文件。为了避免这种情况,可以把配置写在配置文件中,然后通过以下代码引入

ComboPooledDataSource dataSource = new ComboPooledDataSource("testc3p0");

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
 <named-config name="testc3p0">
 <!-- 指定连接数据源的基本属性 -->
 <property name="user">root</property>
 <property name="password">root</property>
 <property name="driverClass">com.mysql.jdbc.Driver</property>
 <property name="jdbcUrl">jdbc:mysql://localhost:3306/library?
useUnicode=true&amp;characterEncoding=UTF-8</property>
 <!-- 若数据库中连接数不⾜时, ⼀次向数据库服务器申请多少个连接 -->DBUtils
DBUtils 可以帮助开发者完成数据的封装(结果集到 Java 对象的映射)
1、导⼊ jar 包
ResultHandler 接⼝是⽤来处理结果集,可以将查询到的结果集转换成 Java 对象,提供了 4 种实现类。
BeanHandler 将结果集映射成 Java 对象 Student
BeanListHandler 将结果集映射成 List 集合 List
MapHandler 将结果集映射成 Map 对象
MapListHandler 将结果集映射成 MapList 结合
 <property name="acquireIncrement">5</property>
 <!-- 初始化数据库连接池时连接的数量 -->
 <property name="initialPoolSize">20</property>
 <!-- 数据库连接池中的最⼩的数据库连接数 -->
 <property name="minPoolSize">2</property>
 <!-- 数据库连接池中的最⼤的数据库连接数 -->
 <property name="maxPoolSize">40</property>
 </named-config>
</c3p0-config>

通过DBUtils简化数据的封装映射(指从结果集到java对象的过程)

可以理解为对上面第四步的简化
实现代码

public static Student findByDBUtils(Integer id){
 Connection connection = null;
 Student student = null;
 try {
 connection = dataSource.getConnection();
 String sql = "select * from student";
 QueryRunner queryRunner = new QueryRunner();
 List<Map<String,Object>> list = queryRunner.query(connection,sql,new
MapListHandler());
 for (Map<String,Object> map:list){
 System.out.println(map);
 }
 } catch (SQLException e) {
 e.printStackTrace();
 } finally {
 try {
 connection.close();
 } catch (SQLException e) {
 e.printStackTrace();
 }
 }
 return student;
}

Q.E.D.