第十章:数据库连接池与DBUtils
一、数据库连接池
1.1 什么是数据库连接池
当我们使用JDBC编程时,在每个请求周期都需要动态地建立相应的数据通路(即会话)。完成操作后需及时关闭这些数据通路(即释放会话),否则会导致资源浪费。例如,在一个高流量网站中(如电商网站),此时系统将对数据库进行一百万次的数据读取操作(包括建立和释放一百万个数据通路)。由于这些反复开启与关闭数据通路过程会导致大量的资源浪费以及整体性能明显下降。为了优化这种场景下的资源管理表现可以通过应用 JDBC 连接池技术可以在运行时动态地管理一组打开的数据通路(即会话)。通过应用 JDBC 连接池技术可以在运行时动态地管理一组打开的数据通路(即会话)。通过应用 JDBC 连接池技术可以在运行时动态地管理一组打开的数据通路(即会话)。
- 应用程序不需要自行创建或关闭连接对象。
- 数据库连接池断开后不销毁对象而归还给自身。
数据库连接池基本参数:
1.初始化大小:数据库连接池里面初始的连接对象个数
2.最大连接数:数据库连接池里面最大的连接对象个数
3.最长使用等待时间:当用户通过本系统中的链接获取资源引用时,在指定的时间段内系统将不再返回新的资源引用。
4.最高空闲容量:在本系统运行过程中,在网络流量趋于平稳状态时系统最多能同时支持的并发客户端连入请求数目。
5.最低保留量:在单条业务逻辑处理过程中,在达到峰值期间系统最多还能为该业务逻辑分配的并发客户端连入请求数目。
优点:采用数据库连接池管理连接对象的方式减少资源的创建和销毁操作,并提升数据库系统的访问速度
1.2 DataSource接口:
数据库连接池技术: sun公司制定了相关规范,并让各个数据库厂商遵循这一标准进行具体实施。
目前市面中较为常见的两种主流技术是DWCp技术和C3p0技术。
1.3 DBCP数据源
DBCP Database Connection Pool (Distributary Connection Pool), a database connection pool technology provided by the Apache organization, is free and open source.
在项目中开发中,使用DBCP的基本步骤:
前提导入DBCP的jar包: commons - dbcp. jar , commons -pool.jar a
DBCP获取连接对象:设置连接参数。
四个连接参数:dr iverName,url, use rname, password.
DBCP获取连接对象具体的方式:
通过手动实现BasicDataSource类的数据源对象初始化方法来获取数据库连接对象。为了使数据源对象能够正常工作,在使用BasicDataSource类时需要手动配置其属性值。从而获取数据库连接对象。以下将通过一个示例详细说明如何使用BasicDataSource类实现数据库连接。

(2)运行main()方法后,运行结果如下:

第二种:通过读取配置文件创建数据源对象,从而获取连接对象
(读取配置的好处:在不修改代码的情况,可以修改数据库的连接参数。)
除了使用BasicDataSource直接创建数据源对象外,还可以使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后获取数据库连接对象。下面通过一个案例来演示,具体步骤如下。
(1)在chapter10项目的src目录下创建dbcpconfig.properties 文件,该文件用于设置数据库的连接信息和数据源的初始化信息。
(2)src目录下创建包cn.itcast.chapter10.example,并在该包下创建一个example02类,该类中采用了从配置文件中获取数据库的连接信息和数据源的初始化信息,具体如下:

1.4 C3PO数据源
在当前数据库连接池领域中,C3PO以其开源性质而广为人知。它实现了DataSource接口,并符合JDBC 2和JDBC 3标准规范,同时具有良好的扩展性和高性能特性。知名开源框架Hibernate和Spring均对其进行了支持。开发人员在使用C3PO数据源时需了解其核心组件ComboPooledDataSource类的相关功能,该组件作为C3P0平台的基础模块,提供了丰富的数据源操作方法。
1.使用ComboPooledDataSource()生成数据源对象
为了使用ComboPooledDataSource()生成数据源对象,请必须手动配置属性值。之后将获取数据库连接对象, 具体步骤如下。
向项目chapter10中引入JAR文件c3p₀-_-₀·₉·₁·₂.jar;随后,在cn.itcast.chapter ₁₀.example目录下定义一个example₀₃类;该类通过手动编码的方式从C₃P₀数据源获取Connection对象。

(2)运行main()方法后,程序的运行结果如图:

调用ComboPooledDataSource构造方法以获取c3p0-config.xml配置文件
在src根目录下建立一个c3p0-config XML文件, 用于配置数据库连接参数及数据初始化设置.
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">
jdbc:mysql://localhost:3306/jdbc
</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="checkoutTimeout">30000</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<named-config name="itcast">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">
jdbc:mysql://localhost:3306/jdbc
</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">15</property>
</named-config>
</c3p0-config>
AI写代码
在cn.itcast.chapter10.example目录内新建一个名为Example04的Java类实例,并使该实例利用C3P0数据源根据配置文件提取必要的信息以获得所需的Connection对象。

(2)运行main()方法后,程序的运行结果如图:

二、DBUtils工具
2.1 DBUtils 工具介绍
QuerRunner类通过精简代码实现了对SQL语句的高效处理。该类通过与ResultHerdler协同工作,这类解决方案能够覆盖大多数数据库操作任务。这一设计显著降低了开发者的编码负担。
QueryRunner类支持一个带有单个参数的构造方法;这个方法通过将javax salv DataSource作为输入提供给该构造函数以生成Connection对象
2.3 ResultSetHandler 接口
该接口用于管理 ResultSet 结果集的转换与查询操作。它能够将 ResultSet 中的数据转换为不同形式的数据以供使用。基于不同数据类型的结果集进行操作和返回相应的信息。
- BeanHandler类负责将 ResultSet 的第一行数据封装成一个 JavaBean 实例,并提供相关的功能。
2.JavaBeanListHandler:负责处理结果集中的每个数据记录并将其包装为对应的JavaBean实例
- ResultSetProcessor 负责将单条记录中的特定字段值保存为 JavaBean 对象。
在 ResultSetHandler 接口中提供了单一方法 handle(java.sql.ResultSet rs),若现有实现无法满足需求,则可自定义一个 ResultSetHandler 实现类,并重写其 handle() 方法以完成所需的结果集处理。
第2.4小节中的ResultSetHandler实现类
在第2.3小节中讨论了关于ResultSetHandler接口中常见实现类的功能
随后,在案例的基础上详细阐述了常见实现类的具体应用方法
- BeanHandler和BeanListHandler
BeanHandler和BeanListHandler所实现的类主要是将结果集中存储的数据打包到对应的JavaBean实例中,并这种方式在实际开发中应用广泛。下面我们将通过代码实践来掌握如何使用这两者及其区别。具体操作步骤如下。
(1)在名为jdbc的数据库中创建数据表user,创建语句如下:
CREATE TABLE user(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL);
AI写代码
向user表插入3条数据,具体语句如下:
INSERT INTO user VALUES(1,'zhangyanju','123456'),
(2,'yiyi','123456'),
(3,'lili','123456')
AI写代码
为了查看数据是否添加成功,使用SELECT语句查询user表.

将下载的DBUtis工具的JAR包com.nio.dbus jdb 1.6.jar添加至项目lib目录下,并将第9章中的JDKUtils.java文件复制至cn.itcast.chapter 10.example包。
在chapter 10项目的cn.itcast.chapter 10.example包中创建一个名为BaseDao类。
该类中编写了一个通用的查询方法,
具体实现如下:

在cn.itcast.chapter 10.example包中生成实体类User,并通过该实体类对User对象进行封装处理,请参考下文以获取具体实现方式。
package chapter10.chapter10.example;
public class User {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
AI写代码
在cnitcast.chapter10.example 包中生成一个名为ResultSetTest1的类。该类专门用于展示BeanHandler对象如何处理结果集。以下为具体代码实现:

位于nicast.chapler.1.example包中创建一个名为RsesTetet的类;该类将用于展示Bensustander类如何处理结果集。具体代码如下:

注:有错误可以抛出异常
over!!!
