由于数据库的连接和释放,都是十分浪费资源的,针对这种情况,我们的前辈就提出了池化技术。
池化技术:预先准备好一些资源放在某个容器中(理解为池子),需要的时候就从该容器中取出某个资源,使用完毕后再将该资源放回这个容器中。
数据库连接池,我们可以理解为存放数据库连接的容器,所有Java的数据库连接池都需要实现Java的java.sql.DataSource接口,这也是Java提出的一种规范。
博主这里分享的是DBCP和C3P0数据库连接池(使用数据库连接池之前需要先导入对应数据库驱动包)。
准备测试的数据库表及数据:
USE `test02`;
CREATE TABLE `student` (
`id` int(11) NOT NULL,
`name` varchar(20) NOT NULL,
`password` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `student`(`id`,`name`,`password`)
values (1,'小米','123456'),
(2,'小明','qwerty'),
(3,'xiaohli','asdfgh'),
(4,'小李','asdfgh'),
(5,'小红','asdfgh');
DBCP
DBCP是Apache下的一个开源的数据库连接池实现,也是Tomcat使用的数据库连接池的组件。
我们单独使用DBCP需要导入两个jar包(分别提供Maven下载地址,需要者去下载对应版本即可):
使用步骤:
- 导入jar包
- 编写配置文件*.properties,博主这里以dbcp-config.properties命名,该配置文件一般放在项目的src路径下。
# 连接设置 这里面的所有键都不能乱写,必须按照DBCP的规定写,否则读取不到
# 驱动和连接数据库
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=rootroot
############ 以下的参数均可不设置(具体可参考源码) ###############
# 初始化连接数
# initialSize=10
# 最大连接数
# maxActive=50
# 最大空闲连接数
# maxIdle=20
# 最小空闲连接数
# minIdle=5
# 超时等待时间(单位:毫秒)
# maxWait=1000
# JDBC驱动建立连接时附带的连接属性
# connectionProperties=useUnicode=true&characterEncoding=utf8
# 指定由连接池所创建的连接是否为自动提交
# defaultAutoCommit=true
# 指定由连接池所创建的连接的只读状态
# defaultReadOnly=
# 指定由连接池所创建的连接的事务级别
# defaultTransactionIsolation=
# ....
- 编写JDBCUtils.java
package cn.ara.demo02;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils_DBCP {
private static DataSource dataSource = null;
static {
try {
//读取配置文件流
InputStream in = JDBCUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcp-config.properties");
//加载配置文件
Properties properties = new Properties();
assert in != null;
//使用UTF-8编码 防止中文配置出现问题
properties.load(new InputStreamReader(in, StandardCharsets.UTF_8));
//根据配置文件创建数据源
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接对象
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//释放资源
public static void close(Connection connection, Statement statement, ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- 编写测试代码
package cn.ara.demo02;
import java.sql.*;
//简单DBCP数据库连接池测试程序
public class JdbcDemo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//获取数据库连接对象
Connection connection = JDBCUtils_DBCP.getConnection();
//获取执行sql语句的对象
Statement statement = connection.createStatement();
//执行sql语句
String sql = "select * from student";
ResultSet resultSet = statement.executeQuery(sql);
//遍历查询结果
while (resultSet.next()) {
System.out.print("id=" + resultSet.getInt("id") + ", ");
System.out.print("name=" + resultSet.getString("name") + ", ");
System.out.print("password=" + resultSet.getString("password"));
System.out.println();
}
//释放连接资源
JDBCUtils_DBCP.close(connection,statement,resultSet);
}
}
- 成功运行结果如下:
C3P0
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。
总之,C3P0是一个开源的数据库连接池,它会自动读取默认xml配置文件(c3p0-config.xml)。
我们单独使用时需要的两个jar包(根据自己的需求在Maven仓库选择版本下载):
使用步骤:
-
导入需要jar包
-
编写配置文件(c3p0-config.xml),放在src目录下
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<!-- new ComboPooledDataSource()表示使用<default-config>默认配置 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test02</property>
<property name="user">root</property>
<property name="password">rootroot</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="checkoutTimeout">3000</property>
</default-config>
<!-- 命名配置 -->
<!-- new ComboPooledDataSource("MYSQL")表示使用<named-config name="MYSQL"> 的配置 -->
<named-config name="MYSQL">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test02</property>
<property name="user">root</property>
<property name="password">rootroot</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">8</property>
<property name="checkoutTimeout">1000</property>
</named-config>
</c3p0-config>
- 编写JDBCUtills工具类
package cn.ara.demo03;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtils_C3P0 {
private static DataSource dataSource = null;
static {
dataSource = new ComboPooledDataSource();
}
//获取数据库连接对象
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//释放资源
public static void close(Connection connection, Statement statement, ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- 编写测试代码
package cn.ara.demo03;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//简单C3P0数据库连接池测试程序
public class JdbcDemo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//获取数据库连接对象
Connection connection = JDBCUtils_C3P0.getConnection();
//获取执行sql语句的对象
Statement statement = connection.createStatement();
//执行sql语句
String sql = "select * from student";
ResultSet resultSet = statement.executeQuery(sql);
//遍历查询结果
while (resultSet.next()) {
System.out.print("id=" + resultSet.getInt("id") + ", ");
System.out.print("name=" + resultSet.getString("name") + ", ");
System.out.print("password=" + resultSet.getString("password"));
System.out.println();
}
//释放连接资源
JDBCUtils_C3P0.close(connection, statement, resultSet);
}
}
成功运行结果如下:
数据库连接池在这一个小小的demo中的感觉并不是那么明显,但是它在对数据库的大量操作的情况下,就会有着很好的性能。
对于数据库连接池,还有很多其他的种类,博主这里就暂介绍这两个,根据具体的情况斟酌选择使用的数据库连接池。