目录
1.连接池概念
2.自定义连接池
3.连接池组件之DBCP
4.连接池组件之C3P0
数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。
数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接(初始连接数),当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。
sun公司规定了连接池需实现的接口(以下两个优秀组件底层也实现了该接口):javax.sql.DataSource。
补充知识:使用代理,可以在不实现接口的情况,对接口的方法进行扩展,添加额外的用户需要的业务逻辑!java中代理的三种模式:静态代理、动态代理、cglib代理(spring)。
动态代理:如果对某个接口中的某个指定的方法的功能进行扩展,而不想实现接口里所有方法,就可以使用动态代理,可以监测接口中方法的执行!
例:
package connectionPool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import org.junit.Test;
/**
* @author xiaohua
* 1.指定全局参数:初始化数目、最大连接数、当前连接数、连接池集合(用于存放初始化连接)
* 2.构造函数:循环创建3个连接
* 3.创建连接的方法
* 4.获取连接的方法
* 5.释放连接的方法
*/
public class MyPool {
//1.指定全局参数
private int init_count=3;
private int max_count=6;
private int current_count=0;
private LinkedList pool=new LinkedList();
//2.构造函数:初始化连接,放入连接池集合
public MyPool() {
for(int i=0;i0) {
return pool.removeFirst();
}
// 4.2 连接池中没有连接: 判断,如果没有达到最大连接数,创建;
if(current_count
//输出结果(没有执行Connection conn7=pool.getConnection();):
//输出结果(若执行Connection conn7=pool.getConnection();):
开源组织Apache提供了一个数据源的独立实现,即DBCP数据库连接池,其中Tomcat就是采用该连接池实现的。
使用时需引入commons-dbcp2-2.5.0.jar、commons-pool2-2.6.0.jar和commons-logging-1.2.jar,下载过程同javaweb学习笔记(十七):JDBC(3) BeanUtils组件。
核心类:BasicDataSource
例:
结构:
Test_DBCP类:
package connectionPool;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.junit.Test;
public class Test_DBCP {
//1.硬编码方式(不推荐)
@Test
public void test1() throws Exception{
// DBCP连接池核心类
BasicDataSource dataSouce = new BasicDataSource();
// 连接池参数配置:初始化连接数、最大连接数 / 连接字符串、驱动、用户、密码
dataSouce.setUrl("jdbc:mysql:///xiaohua"); //数据库连接字符串
dataSouce.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动
dataSouce.setUsername("root");//数据库连接用户
dataSouce.setPassword("root"); //数据库连接密码
dataSouce.setInitialSize(3); // 初始化连接
dataSouce.setMaxTotal(6); // 最大连接
dataSouce.setMaxIdle(3000); // 最大空闲时间,单位:毫秒
// 获取连接
Connection con = dataSouce.getConnection();
con.prepareStatement("SELECT * FROM student WHERE id=2").executeQuery();
// 关闭
con.close();
}
@Test
// 2. 配置方式实现连接池 , 便于维护
public void testProp() throws Exception {
// 加载prop配置文件
Properties prop = new Properties();
// 获取文件流
InputStream inStream = Test_DBCP.class.getResourceAsStream("db.properties");
// 加载属性配置文件
prop.load(inStream);
// 根据prop配置,直接创建数据源对象
DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);
// 获取连接
Connection con = dataSouce.getConnection();
con.prepareStatement("delete from student where id=6").executeUpdate();
// 关闭
con.close();
}
}
db.properties文件:
url=jdbc:mysql:///xiaohua
driverClassName=com.mysql.jdbc.Driver
username=root
password=root
initialSize=3
masActive=6
maxIdle=3000
C3P0连接池是最常用的连接池技术。Spring框架,默认支持C3P0连接池技术!
下载地址:http://sourceforge.net/projects/c3p0/ 使用时需引入其中的c3p0-0.9.5.2.jar包和mchange-commons-java-0.2.11.jar包。
c3p0使用c3p0-config.xml来配置参数信息,并放在src目录下,其中
①default-config配置默认访问数据库的信息,相应的使用
ComboPooledDataSource dataSource = new ComboPooledDataSource();
来使用默认的配置来创建数据源。
②named-config放置指定的数据库访问源信息,相应的使用
ComboPooledDataSource ds = new ComboPooledDataSource("mysql_config");来使用指定名称的配置信息来创建数据源。
核心类:CombopooledDataSource
例:
结构:
Test_c3p0.java:
package connectionPool;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class Test_C3P0 {
@Test
//1. 硬编码方式,不推荐
public void testCode() throws Exception {
// 创建连接池核心工具类
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/xiaohua");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(1000);
// 从连接池对象中,获取连接对象
Connection con = dataSource.getConnection();
// 执行更新
con.prepareStatement("delete from student where id=7").executeUpdate();
// 关闭
con.close();
}
@Test
//2. XML配置方式,使用C3P0连接池管理连接
public void test2() throws Exception {
// 创建c3p0连接池核心工具类
// 自动加载src下c3p0的配置文件【c3p0-config.xml】
ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置来创建数据源
//ComboPooledDataSource ds = new ComboPooledDataSource("mysql_config");”使用指定名称的配置信息来创建数据源
PreparedStatement pstmt = null;
// 获取连接
Connection con = dataSource.getConnection();
for (int i=1; i<11;i++){
String sql = "insert into student(name,age) values(?,?)";
// 执行更新
pstmt = con.prepareStatement(sql);
pstmt.setString(1, "xiaohua" + i);
pstmt.setInt(2, 20+i);
pstmt.executeUpdate();
}
pstmt.close();
// 关闭
con.close();
}
}
c3p0-config.xml文件:
jdbc:mysql://localhost:3306/xiaohua
com.mysql.jdbc.Driver
root
root
3
6
1000
jdbc:mysql://localhost:3306/xiaohua
com.mysql.jdbc.Driver
root
root
3
6
1000
使用数据库客户端工具,可以看到,id=7的已经删除,并且已插入十个信息在最后: