一、连接池的概念及其作用

  • 池:降低系统资源开销,提高程序执行效率,优化程序服务器性能等,此处指广义上的池的作用
  • 常见的池:数据库连接池、线程池、内存池、对象池等
  • 池的设计思想:以可复用性为中心设计,提高效率
  • 数据库连接池:用从连接池中获得的连接与数据库通迅

二、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

java 在连接池中查看多个数据库的连接 java常见连接池_默认值