一、连接池的概念及其作用
- 池:降低系统资源开销,提高程序执行效率,优化程序服务器性能等,此处指广义上的池的作用
- 常见的池:数据库连接池、线程池、内存池、对象池等
- 池的设计思想:以可复用性为中心设计,提高效率
- 数据库连接池:用从连接池中获得的连接与数据库通迅
二、DataSource接口
- DataSource(数据源)
- 包位置:java.sql.DataSource
- 是连接池必须实现的接口
- 该接口中定义的两个重载的方法
Connection getConnection()
Connection getConnection(String username, String password)
三、常用的开源数据连接池
1.DBCP 数据库连接池 (tomcat)
1.<!-- 数据源 -->
2. <bean id="dataSource"
3. class="org.apache.commons.dbcp.BasicDataSource"
4. destroy-method="close">
5. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
6. <property name="url" value="jdbc:mysql://192.168.0.109:3306/test? useUnicode=true&characterEncoding=UTF-8"/>
7. <property name="username" value="root"/>
8. <property name="password" value="root"/>
9. <!--maxActive: 最大连接数量-->
10. <property name="maxActive" value="150"/>
11. <!--minIdle: 最小空闲连接-->
12. <property name="minIdle" value="5"/>
13. <!--maxIdle: 最大空闲连接-->
14. <property name="maxIdle" value="20"/>
15. <!--initialSize: 初始化连接-->
16. <property name="initialSize" value="30"/>
17. <!-- 连接被泄露时是否打印 -->
18. <property name="logAbandoned" value="true"/>
19. <!--removeAbandoned: 是否自动回收超时连接-->
20. <property name="removeAbandoned" value="true"/>
21. <!--removeAbandonedTimeout: 超时时间(以秒数为单位)-->
22. <property name="removeAbandonedTimeout" value="10"/>
23. <!--maxWait: 超时等待时间以毫秒为单位-->
24. <property name="maxWait" value="1000"/>
25. <!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. -->
26. <property name="timeBetweenEvictionRunsMillis" value="10000"/>
27. <!-- 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 -->
28. <property name="numTestsPerEvictionRun" value="10"/>
29. <!-- 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程-->
30. <property name="minEvictableIdleTimeMillis" value="10000"/>
31. <property name="validationQuery" value="SELECT NOW() FROM DUAL"/>
32. </bean>
释意
参数 | 描述 |
username | 传递给JDBC驱动的用于建立连接的用户名 |
password | 传递给JDBC驱动的用于建立连接的密码 |
url | 传递给JDBC驱动的用于建立连接的URL |
driverClassName | 使用的JDBC驱动的完整有效的java 类名 |
connectionProperties | 当建立新连接时被发送给JDBC驱动的连接参数, |
注意: 1格式为[propertyName=property;] 可理解为键值对 2. 参数user/password将被明确传递,所以不需要包括在这里。 |
参数 默认值 描述
defaultAutoCommit true 连接池创建的连接的默认的auto-commit状态
defaultReadOnly driver default 连接池创建的连接的默认的read-only状态.
如果没有设置则setReadOnly方法将不会被调用. (某些驱动不支持只读模式,比如:Informix)
defaultTransactionIsolation driver default 连接池创建的连接的默认的TransactionIsolation状态.
下面列表当中的某一个: (参考javadoc)
* NONE
* READ_COMMITTED
* READ_UNCOMMITTED
* REPEATABLE_READ
* SERIALIZABLE
defaultCatalog 连接池创建的连接的默认的catalog
参数 默认值 描述
initialSize 0 初始化连接:连接池启动时创建的初始化连接数量,1.2版本后支持
maxActive 8 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量,
如果设置为非正数则表示不限制
maxIdle 8 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,
如果设置为负数表示不限制
minIdle 0 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,
如果设置为0则不创建
maxWait 无限 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),
超过时间则抛出异常,如果设置为-1表示无限等待
参数 默认值 描述
validationQuery SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,
则查询必须是一个SQL SELECT并且必须返回至少一行记录
testOnBorrow true 指明是否在从池中取出连接前进行检验,如果检验失败,
则从池中去除连接并尝试取出另一个.
注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
testOnReturn false 指明是否在归还到池中前进行检验
注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
testWhileIdle false 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,
则连接将被从池中去除.
注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
timeBetweenEvictionRunsMillis -1 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位.
如果设置为非正数,则不运行空闲连接回收器线程
numTestsPerEvictionRun 3 在每次空闲连接回收器线程(如果有)运行时检查的连接数量
minEvictableIdleTimeMillis 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程
(如果有)回收的最小时间值,单位毫秒
参数 默认值 描述
poolPreparedStatements false 开启池的prepared statement 池功能
maxOpenPreparedStatements 不限制 statement池能够同时分配的打开的statements的最大数量,
如果设置为0表示不限制
这里可以开启PreparedStatements池. 当开启时, 将为每个连接创建一个statement池,
并且被下面方法创建的PreparedStatements将被缓存起来:
* public PreparedStatement prepareStatement(String sql)
* public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
注意: 确认连接还有剩余资源可以留给其他statement
参数 默认值 描述
accessToUnderlyingConnectionAllowed false 控制PoolGuard是否容许获取底层连接
如果容许则可以使用下面的方式来获取底层连接:
Connection conn = ds.getConnection();
Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();
...
conn.close();
默认false不开启, 这是一个有潜在危险的功能, 不适当的编码会造成伤害.
(关闭底层连接或者在守护连接已经关闭的情况下继续使用它).请谨慎使用,
并且仅当需要直接访问驱动的特定功能时使用.
注意: 不要关闭底层连接, 只能关闭前面的那个.
参数 默认值 描述
removeAbandoned false 标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制.
如果设置为true, 连接被认为是被泄露并且可以被删除,如果空闲时间超过removeAbandonedTimeout.
设置为true可以为写法糟糕的没有关闭连接的程序修复数据库连接.
removeAbandonedTimeout 300 泄露的连接可以被删除的超时值, 单位秒
logAbandoned false 标记当Statement或连接被泄露时是否打印程序的stack traces日志。
被泄露的Statements和连接的日志添加在每个连接打开或者生成新的Statement,
因为需要生成stack trace。
如果开启"removeAbandoned",那么连接在被认为泄露时可能被池回收. 这个机制在(getNumIdle() < 2)
and (getNumActive() > getMaxActive() - 3)时被触发.
举例当maxActive=20, 活动连接为18,空闲连接为1时可以触发"removeAbandoned".
但是活动连接只有在没有被使用的时间超过"removeAbandonedTimeout"时才被删除,默认300秒.
在resultset中游历不被计算为被使用.
2.C3P0 数据库连接池 (hibernate)
<c3p0-config>
<default-config>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">3</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">30</property>
<!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
<property name="acquireRetryDelay">1000</property>
<!--连接关闭时默认将所有未提交的操作回滚。Default: false -->
<property name="autoCommitOnClose">false</property>
<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么
属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试
使用。Default: null-->
<property name="automaticTestTable">Test</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->
<property name="breakAfterAcquireFailure">false</property>
<!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出
SQLException,如设为0则无限期等待。单位毫秒。Default: 0 -->
<property name="checkoutTimeout">100</property>
<!--通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全路径。
Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
<property name="connectionTesterClassName"></property>
<!--指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可
Default: null-->
<property name="factoryClassLocation">null</property>
<!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs.
(文档原文)作者强烈建议不使用的一个属性-->
<property name="forceIgnoreUnresolvedTransactions">false</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">60</property>
<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">3</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">60</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">15</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
<property name="maxStatements">100</property>
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
<property name="maxStatementsPerConnection"></property>
<!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能
通过多线程实现多个操作同时被执行。Default: 3-->
<property name="numHelperThreads">3</property>
<!--当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0
的数据源时。Default: null-->
<property name="overrideDefaultUser">root</property>
<!--与overrideDefaultUser参数对应使用的一个参数。Default: null-->
<property name="overrideDefaultPassword">password</property>
<!--密码。Default: null-->
<property name="password"></property>
<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:
测试的表必须在初始数据源的时候就存在。Default: null-->
<property name="preferredTestQuery">select id from test where id=1</property>
<!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->
<property name="propertyCycle">300</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">false</property>
<!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->
<property name="testConnectionOnCheckin">true</property>
<!--用户名。Default: null-->
<property name="user">root</property>
<!--早期的c3p0版本对JDBC接口采用动态反射代理。在早期版本用途广泛的情况下这个参数
允许用户恢复到动态反射代理以解决不稳定的故障。最新的非反射代理更快并且已经开始
广泛的被使用,所以这个参数未必有用。现在原先的动态反射与新的非反射代理同时受到
支持,但今后可能的版本可能不支持动态反射代理。Default: false-->
<property name="usesTraditionalReflectiveProxies">false</property>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">25</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">0</property>
<user-overrides user="swaldman">
</user-overrides>
</default-config>
<named-config name="dumbTestConfig">
<property name="maxStatements">200</property>
<user-overrides user="poop">
<property name="maxStatements">300</property>
</user-overrides>
</named-config>
</c3p0-config>
3.相关包
4.特点
都是开源的连接池
五、代码示例
5.1建库建表并插入测试数据
CREATE DATABASE Admin DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci /*建库*/
USE admin /*使用此库*/
CREATE TABLE admin( /*建表*/
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(12) NOT NULL,
pwd VARCHAR(12) NOT NULL
)
/*测试数据*/
INSERT INTO admin(username,pwd) VALUES('王五','1234');
INSERT INTO admin(username,pwd) VALUES('张三','1234');
INSERT INTO admin(username,pwd) VALUES('李四','1234');
5.2实体类
package work.itcase.entity;
public class Admin {
private int id;
private String userName;
private String pwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Admin(int id, String userName,String pwd){
super();
this.id = id;
this.userName = userName;
this.pwd = pwd;
}
public Admin(){
}
@Override
public String toString() {
return "Admin [id=" + id + ", userName=" + userName + ", pwd=" + pwd
+ "]";
}
}
5.3(crud)测试类
package work.itcase.entity;
import java.sql.Connection;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
import work.itcase.utils.JdbcUtil;
public class Apptest {
// 一. 使用Dbutils组件更新
private Connection con = null;
@Test
public void deletetest() throws Exception {
// 0.需要操作的sql
String sql = "delete from admin where id = 2 ";
// 1.创建连接
con = JdbcUtil.getConnection();
// 1.2创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3更新
qr.update(con, sql);
con.close();
}
// 二、使用Dbutils组件添加
@Test
public void inserttest() throws Exception {
// 0.需要操作的sql
// String sql = "insert into admin values(?,?,?)";
String sql = "insert into admin values(2,'张平','0000');";
// 1.创建连接
con = JdbcUtil.getConnection();
// 1.2创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3更新
qr.update(con, sql);
// qr.update(sql,admin.getId(),admin.getUserName(),admin.getPwd());
con.close();
}
// 三、使用Dbutils组件修改
@Test
public void testUpdate() throws Exception {
// 0.需要操作的sql
String sql = "update admin set userName = '赵七',pwd = '0000' where id =3";
// String sql = "update set userName =?,pwd = ? where id =?";
// 1.创建连接
con = JdbcUtil.getConnection();
// 1.2创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3更新
// qr.update(sql,admin.getId(),admin.getUserName(),admin.getPwd());
qr.update(con, sql);
con.close();
}
// 四.使用Dbutils组件查询
@Test
public void testQuery() throws Exception {
String sql = "select * from admin";
// 1.1 连接
Connection con = JdbcUtil.getConnection();
// 1.2 创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3 查询
List<Admin> list = qr.query(con, sql, new BeanListHandler<Admin>(
Admin.class));
/*
* qr.query(参数一,参数二,参数三) 参数三:需实现的接口 可以是自定义的接口 也可以是默认接口 常用的默认接口:
* 1.BeanHandler: 查询返回单个对象 2.BeanListHandler: 查询返回list集合,集合元素是指定的对象
* 3.ArrayHandler, 查询返回结果记录的第一行,封装对对象数组, 即返回:Object[]
* 4.ArrayListHandler, 把查询的每一行都封装为对象数组,再添加到list集合中
* 5.ScalarHandler查询返回结果记录的第一行的第一列 (在聚合函数统计的时候用)
* 6. MapHandler 查询返回结果的第一条记录封装为map
*/
System.out.println(list);
con.close();
}
}
5.4自定义连接池类
package work.itcase.pool;
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;
/**
* 自定义连接池类
* 作用:自定义连接池,管理连接
* @author Administrator
*
*/
public class MyPool {
private int initCount = 3; // 初始化连接数目
private int maxCount = 6; // 最大连接数
private int currentCount = 0; // 记录当前使用的连接数
// 1.连接池(存放所有的初始化连接)
private LinkedList<Connection> pool = new LinkedList<Connection>();
// 构造函数(初始化成员变量)初始化连接放入连接池
public MyPool() {
// 初始化连接
for (int i = 0; i < initCount; i++) {
// 记录当前连接数目
currentCount++;
// 创建原始的链接对象
Connection conn = createConnection();
// 把连接加入连接池中
pool.addLast(conn);
}
}
// 2.创建一个新的连接的方法
private Connection createConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
// 原始的目标对象
final Connection conn = DriverManager.getConnection(
"jdbc:mysql:///admin", "root", "0000");
/* ####使用动态代理技术构建连接池中的connection
####*/
Connection proxy = (Connection) Proxy.newProxyInstance(conn
.getClass().getClassLoader(),
new Class[] { Connection.class }, new InvocationHandler() {
// 重写invocatinHadler alt +shift +s
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 方法返回值
Object result = null;
// 当前执行的方法的方法名
String methodName = method.getName();
// 判断当前执行close方法的时候,把连接放入连接池
if ("close".equals(methodName)) {
System.out.println("begin:当前执行了close方法开始!");
// 连接放入连接池判断
pool.addLast(conn);
System.out.println("end:当前执行close方法结束!");
} else {
// 调用目标对象方法
result = method.invoke(conn, args);
}
return result;
}
});
return proxy;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
// 3.获取连接池
public Connection getConnection() {
// 3.1 判断连接池中是否有连接, 如果有连接,就直接从连接池取出
if (pool.size() > 0) {
return pool.removeFirst();
}
// 3.2 连接池中没有连接: 判断,如果没有达到最大连接数,创建;
if (currentCount < maxCount) {
// 记录当前使用的连接数
currentCount++;
// 创建连接
return createConnection();
}
// 3.3 如果当前已经达到最大连接数,抛出异常
throw new RuntimeException("当前连接数已经达到上限!");
}
// 4.释放连接
public void realeaseConneciton(Connection conn) {
// 4.1 判断: 池的数目如果小于初始化连接,就放入池中
if (pool.size() < initCount) {
pool.addLast(conn);
} else {
// 4.2关闭
currentCount--;
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void main(String args[]) throws SQLException {
MyPool pool = new MyPool();
System.out.println("当前连接:" + pool.currentCount);
// 使用连接
pool.getConnection();
pool.getConnection();
Connection conn4 = pool.getConnection();
Connection conn3 = pool.getConnection();
Connection conn2 = pool.getConnection();
Connection conn1 = pool.getConnection();
conn1.close();
// 再获取
pool.getConnection();
System.out.println("连接池:" + pool.pool.size()); // 0
System.out.println("当前连接: " + pool.currentCount); // 3
}
}
自定义连接池的步骤总结
1.自定义连接池类MyPool
2.指定全局参数 初始化数目、最大连接数、当前连接、 连接池集合
3.构造函数:循环创建3个连接
4.创建一个连接的方法
4.1建立数据库原始连接
4.2使用动态代理技术构建连接池中的connection
4.2.1重写invocatinHadler alt +shift +s
4.2.1.1定义当前执行的方法的方法名
4.2.1.2判断当前执行close方法的时候,把连接放入连接池
4.2.1.3连接放入连接池判断
4.2.1.4调用目标对象方法
5.获取连接
5.1判断连接池中是否有连接, 如果有连接,就直接从连接池取出
5.2连接池中没有连接: 判断,如果没有达到最大连接数,创建;
5.3如果当前已经达到最大连接数,抛出异常
6.释放连接
6.1判断: 池的数目如果小于初始化连接,就放入池中
6.2关闭资源
5.5DBCP使用
package work.itcase.dbcp;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;
public class DBCPtest {
// 1. 硬编码方式实现连接池
@Test
public void testDbcp() throws Exception {
// DBCP连接池核心类
BasicDataSource dataSouce = new BasicDataSource();
// 连接池参数配置:初始化连接数、最大连接数 / 连接字符串、驱动、用户、密码
dataSouce.setUrl("jdbc:mysql:///admin?characterEncoding=utf8"); //数据库连接字符串
dataSouce.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动
dataSouce.setUsername("root"); //数据库连接用户
dataSouce.setPassword("0000"); //数据库连接密码
dataSouce.setInitialSize(3); // 初始化连接
dataSouce.setMaxActive(6); // 最大连接
dataSouce.setMaxIdle(3000); // 最大空闲时间
// 获取连接
Connection conn = dataSouce.getConnection();
conn.prepareStatement("delete from admin where id=3").executeUpdate();
// 关闭
conn.close();
}
@Test
// 2. 【推荐】配置方式实现连接池 , 便于维护
public void testProp() throws Exception {
// 加载prop配置文件
Properties prop = new Properties();
// 获取文件流
InputStream inStream = DBCPtest.class.getResourceAsStream("db.properties");
// 加载属性配置文件
prop.load(inStream);
// 根据prop配置,直接创建数据源对象
DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);
// 获取连接
Connection con = dataSouce.getConnection();
con.prepareStatement("delete from admin where id=4").executeUpdate();
// 关闭
con.close();
}
}
db.properties文件
url=jdbc:mysql:///admin?characterEncoding=utf8
driverClassName=com.mysql.jdbc.Driver
username=root
password=0000
initialSize=3
maxActive=6
maxIdle=3000
5.6.C3P0 数据库连接池的使用
<c3p0-config>
<default-config>
<!-- 需要连接的数据库地址 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/admin?characterEncoding=utf8
</property>
<!-- 数据库驱动 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!--用户名。Default: null -->
<property name="user">root</property>
<!--密码。Default: null -->
<property name="password">0000</property>
<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">3</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">6</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">1000</property>
</default-config>
<named-config name="oracle_config">
<property name="jdbcUrl">jdbc:mysql://localhost:3306/admin?characterEncoding=utf8</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">0000</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">1000</property>
</named-config>
</c3p0-config>
package work.itcase.c3p0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0test {
@Test
//1. 硬编码方式,使用C3P0连接池管理连接
public void testCode() throws Exception {
// 创建连接池核心工具类
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/admin?characterEncoding=utf8");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUser("root");
dataSource.setPassword("0000");
dataSource.setInitialPoolSize(3); //初始时获取的三个连接
dataSource.setMaxPoolSize(6); // 最大连接数
dataSource.setMaxIdleTime(1000); // 最大空闲时间
// ---> 从连接池对象中,获取连接对象
Connection conn = dataSource.getConnection();
// 执行更新
conn.prepareStatement("delete from admin where id=1").executeUpdate();
// 关闭
conn.close();
}
@Test
//2. XML配置方式,使用C3P0连接池管理连接
public void testXML() throws Exception {
// 创建c3p0连接池核心工具类
// 自动加载src下c3p0的配置文件【c3p0-config.xml】
ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置
PreparedStatement pstmt = null;
// 获取连接
Connection conn = dataSource.getConnection();
for (int i=1; i<11;i++){
String sql = "insert into admin(username,pwd) values(?,?)";
// 执行更新
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "Rose" + i);
pstmt.setString(2, "0000");
pstmt.executeUpdate();
}
pstmt.close();
// 关闭
conn.close();
}
}
查看活跃的l连接列表
SHOW PROCESSLIST