Chapter 10 数据库连接池与DBUtils工具
10.1 数据库连接池
JDBC由于每操作一次数据库,都会执行一次创建和断开Connection对象的操作,这种频繁的操作Connection对象十分影响数据库的访问效率,并且增加了代码量。Apache组织提供了DBUtils工具类库,该类库实现了对JDBC的简单封装,能在不影响性能的情况下极大地简化JDBC的编码工作。
—— 什么是数据库连接池
在JDBC编程中,每次创建和断开Connection对象都会消耗一定时间和IO资源。这是因为Java程序与数据库之间建立连接时,数据库端要验证用户名和密码,并且要为这个连接分配资源,Java程序则要把代表连接的java.sql.Connection对象等加载到内存中,所以建立数据库连接的开销大,尤其是在大量的并发访问时。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,当应用程序访问数据库时并不是直接创建Connection,而是向连接池“申请”一个Connection。如果连接池中有空闲的Connection,则将其返回,否则创建新的Connection。使用完毕后,连接池会将该Connection回收,并交付其他的线程使用,以减少创建和断开数据库的连接次数,提高数据库的访问效率。
—— DataSource 接口
负责与数据库建立连接,并定义了返回值为Connection对象的方法,如下
- Connection getConnection()
- Connection getConnection(String username, String password)
相同点,它们都能用来获取Connection对象,不同点,第1个方法是通过无参的方式建立与数据库的连接,第2个方法是通过传入登录信息的方式建立与数据库的连接。
通常把实现了javax.sql.DataSource接口的类称为数据源。数据源中存储了所有建立数据库连接的信息,通过提供正确的数据源名称,可以找到相应的数据库连接。
数据源中包含数据库连接池。如果数据是水,数据库就是水库,数据源就是连接到水库的管道,终端用户看到的数据集是管道里流出来的水。一些开源组织提供了数据源的独立实现,常用的有DBCP数据源和C3P0数据源。
—— DBCP(DataBase Connection Pool) 数据源
它是Apache组织下的开源连接池实现,也是Tomcat服务器使用的连接池组件。单独使用DBCP数据源时,需要在应用程序中导入两个JAR包,如下
1.commons-dbcp.jar包
commons-dbcp.jar包是DBCP数据源的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了DataSource接口的getConnection()方法。
2.commons-pool.jar包
commons-pool.jar包是DBCP数据库连接池实现包的依赖包,为commons-dbcp.jar包中的方法提供了支持。
commons-dbcp.jar中包含两个核心的类,分别是BasicDataSourceFactory和BasicDataSource,它们都包含获取DBCP数据源对象的方法。
BasicDataSource是DataSource接口的实现类,主要包括设置数据源对象的方法,该类的常用方法如下
BasicDataSourceFactory是创建BasicDataSource对象的工厂类,它包含一个返回值为BasicDataSource对象的方法createDataSource(),该方法通过读取配置文件的信息生成数据源对象并返回给调用者。这种把数据库的连接信息和数据源的初始化信息提取出来写进配置文件的方式,让代码看起来更加简洁,思路也更加清晰。
使用DBCP数据源时,首先要创建数据源对象,数据源对象的创建方式有两种如下:
1.通过BasicDataSource类直接创建数据源对象
在使用BasicDataSource类创建一个数据源对象时,需要手动给数据源对象设置属性值,然后获取数据库连接对象。案例如下:
(1)创建Web项目,导入mysql-connector-java-5.0.8-bin.jar、commons-dbcp-1.4.jar以及commons-pool-1.6.jar这三个包。
package cn.itcast.chapter10.example;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import com.mysql.cj.jdbc.DatabaseMetaData;
public class Example01 {
public static DataSource ds = null;
static {
//获取DBCP数据源实现类对象
BasicDataSource bds = new BasicDataSource();
//设置连接数据库需要的配置信息
bds.setDriverClassName("com.mysql.jsbc.Driver");
bds.setUrl("jdbc:mysql://localhost:3306/jdbc");
bds.setUsername("root");
bds.setPassword("itcast");
//设置连接池的参数
bds.setInitialSize(5);
bds.setMaxActive(5);
ds = bds;
}
public static void main(String[] args) throws SQLException {
//获取数据库连接对象
Connection conn = ds.getConnection();
//获取数据库连接信息
DatabaseMetaData metaData = conn.getMetaData();
//打印数据库连接信息
System.out.println(metaData.getURL()+",UserName="+metaData.getUserName()+","+metaData.getDriverName());
}
}
(2)运行main()方法后,程序的运行结果如图
2.通过读取配置文件创建数据源对象
即使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后读取数据库连接对象。
(1)在src目录下创建dbcpconfig.properties文件,该文件用于设置数据库的连接信息和数据源的初始化信息,如图
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc
username=root
password=itcast
#初始化连接
initialSize=5
#最大连接数量
maxActive=10
#最大空闲连接
maxIdle=10
(2)创建Example02类,该类中采取了从配置文件中获取数据库的连接信息的数据源的初始化信息的方式
package cn.itcast.chapter10.example;
import java.io.InputStream;
import java.sql.SQLException;
import javax.activation.DataSource;
import javax.jms.ConnectionMetaData;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import com.mysql.cj.jdbc.DatabaseMetaData;
import com.sun.xml.internal.fastinfoset.sax.Properties;
public class Example02 {
public static DataSource ds = null;
static {
//新建一个配置文件对象
Properties prop = new Properties();
try {
//通过类加载器找到文件路径,读取配置文件
InputStream in = new Example02().getClass().getClassLoader().getResourceAsStream("dbcpconfig.properties");
//把文件以输入流的形式加载到配置对象中
prop.load(in);
//创建数据对象
ds = BasicDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static void main(String[] args) throws SQLException {
//获得数据库连接对象
ConnectionMetaData conn = ds.getConnection();
//获取数据库连接信息
DatabaseMetaData metaData = conn.getMetaData();
//打印数据库连接信息
System.out.println(metaData.getURL()+",UserName="+metaData.getUserName()+","+metaData.getDriverName());
}
}
—— C3P0 数据源
C3P0是目前最流行的开源数库连接池之一,它实现了DataSource数据源接口,支持JDBC2和JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架Hibernate和Spring都支持该数据源。在使用C3P0开发时,需要了解C3P0中DataSource接口的实现类ComboPooleDataSource,它是C3P0的核心类,提供了数据源对象的相关方法,如下
当使用C3P0数据源时,首先需要创建数据源对象,创建数据源对象可以使用ComboPooledDataSource类,该类有两个构造方法,分别是ComboPooleDataSource()和ComboPooledDataSource(String configName)。如下
1.通过ComboPooleDataSource()构造方法创建数据源对象
需要手动给数据源对象设置属性值,然后获取数据库连接对象,步骤如下
(1)在项目chapter10中导入JAR包c3p0-0.9.1.2.jar,然后在cn.itcast.chapter10.example包下创建一个Example03类,该类采用C3P0数据源手动代码的方式获取Connection对象,如下
package cn.itcast.chapter10.example;
import java.sql.SQLException;
import javax.activation.DataSource;
public class Example03 {
public static DataSource ds = null;
//初始化C3P0数据源
static {
ComboPooledDataSource cpds = new ComboPooledDataSource();
//设置连接数据需要的配置信息
try {
cpds.setDirverClass("com.mysql.jdbc.Dirver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc");
cpds.setUser("root");
cpds.setPassword("itcast");
//设置连接池的参数
cpds.setInitialPoolSize(5);
cpds.setMaxPoolSize