数据库连接池概述
在JDBC编程中,每次创建和断开Connection对象都会消耗一定的时间和IO资源。这是因为在Java程序中与数据库之间建立连接时,加上数据库端要验证用户名和密码并为该连接分配资源,而程序则要把代表连接Connection对象加载到内存中,所以建立数据库连接的开销很大。尤其是在大量的并发访问时,频繁地创建、断开数据库连接势必会影响数据库的访问效率,甚至导致数据库崩溃。
为了解决该类问题的发生诞生了数据库连接池技术。数据库连接池负责分配、管理和释放数据库连接,它允许在应用程序重复使用现有的数据库连接,而不是每次都重新建立连接。
两种常见的连接池:DBCP 和 C3P0
DBCP
DBCP(DataBase Connection Pool)由Apache研发,而且Tomcat的连接池也正是采用DBCP实现的,该数据库连接池既可与应用服务器整合使用,也可由应用程序独立使用。
配置文件:
#<!-- 连接设置 -->
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#<!-- 最大连接数量 -->
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间(单位毫秒) -->
maxWait=50000
#<!-- 编码方式 -->
connectionProperties=useUnicode=true;characterEncoding=utf8
##<!-- 指定由连接池所创建的连接自动提交 -->
defaultAutoCommit=true
#<!-- 指定由连接池所创建的连接的事务级别 -->
defaultTransactionIsolation=REPEATABLE_READ
编写操作DBCP的工具类
package com.util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DBCPUtil {
private static DataSource dataSource = null;
// 创建数据库连接池
static {
Properties properties = new Properties();
try {
ClassLoader classLoader = DBCPUtil.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("dbcpconfig.properties");
properties.load(resourceAsStream);
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 创建连接
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 释放连接
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
使用DBPC
package com.ycy1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.util.DBCPUtil;
public class Test02 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = DBCPUtil.getConnection();
String sql = "select * from student";
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
int sid = resultSet.getInt("studentid");
String sname = resultSet.getString("studentname");
Student student = new Student(sid, sname);
System.out.println(student);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBCPUtil.release(connection, preparedStatement, resultSet);
}
}
}
测试结果
C3P0
C3P0是目前最流行的开源数据库连接池之一,它支持 JDBC2和JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架Hibernate和 Spring使用的数据源正是C3P0。
配置文件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/mydb</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">15</property>
<property name="maxIdleTime">40</property>
<property name="maxPoolSize">150</property>
<property name="minPoolSize">20</property>
</default-config>
</c3p0-config>
编写操作C3P0的操作类
package com.util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Util {
// 创建数据库连接池
private static DataSource dataSource = new ComboPooledDataSource();
// 创建连接
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 释放资源
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
使用C3P0
package com.ycy1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mchange.v2.c3p0.cfg.C3P0Config;
import com.util.C3P0Util;
public class Test03 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = C3P0Util.getConnection();
String sql = "select * from student";
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
int sid = resultSet.getInt("studentid");
String sname = resultSet.getString("studentname");
Student student = new Student(sid, sname);
System.out.println(student);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
C3P0Util.release(connection, preparedStatement, resultSet);
}
}
}
测试结果: