目前常用的主流Java数据库连接池有:Druid,Proxool,c3p0,DBCP等,他们都是开源项目且使用率极高,由于DBCP 的bug 较多Hibernate 已经在新版本中不支持其扩展,所以接下来我们主要学习一下proxool 和c3p0,这篇文章主要介绍c3p0 的使用及配置。
c3p0 实现了数据源与JNDI 的绑定,支持JDBC3 规范和JDBC2 的标准扩展。使用它的开源项目有很多,比较著名的如:Hibernate,Spring 等,并且hibernate 开发组推荐使用c3p0。
c3p0 下载:http://sourceforge.net/projects/c3p0/
c3p0 指南:http://www.mchange.com/projects/c3p0/
在c3p0 指南里有非常详细的设置及部署步骤,但只有英文版本。目前c3p0 的最新版本是0.9.2.1。
下面开始介绍c3p0 的使用及配置:
1.下载c3p0:
从官网下载之后解压缩得到以下目录结构内容:
目录结构非常简洁清晰,分别是文档,实例,类库,源码和许可协议等文件。
2.新建Java项目:
(1) 项目命名为jdbc_test,并新建一个Java 接口,命名为getUsrInfoWithC3P0,如下所示:
package com.test.jdbc.dao;
public interface TestDAO {
/**
* 获取用户信息
* @param usrId
*/
void getUsrInfoWithC3P0(Integer usrId);
}
代码比较简单,就是一个根据用户ID 获取用户信息的方法。
接下来在build path中添加c3p0 和mchange-commons 的jar包。
(2) 新建class 类TestDAOImpl 并实现TestDAO 接口,在getUsrInfo 方法中添加代码:
package com.test.jdbc.dao.impl;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.test.jdbc.dao.TestDAO;
public class TestDAOImpl implements TestDAO {
/**
* c3p0实现
*/
public void getUsrInfoWithC3P0(Integer usrId) {
ComboPooledDataSource cpds=new ComboPooledDataSource();
String sql="SELECT * FROM USER u WHERE u.USR_ID=" + usrId;
String driver="com.mysql.jdbc.Driver";
String jdbcUrl="jdbc:mysql://192.168.0.14:3306/test";
String user="moster";
String passwd="shzygjrmdwg";
Connection conn=null;
try {
cpds.setDriverClass(driver);
cpds.setJdbcUrl(jdbcUrl);
cpds.setUser(user);
cpds.setPassword(passwd);
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
conn=cpds.getConnection();
Statement st=conn.createStatement();
ResultSet result=st.executeQuery(sql);
while(result.next()) {
System.out.println("Name:" + result.getString("NAME"));
}
result.close();
st.close();
conn.close();
} catch(PropertyVetoException e) {
e.printStackTrace();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
(3) 新建一个class 类,里面写上main 函数来测试我们的DAO 代码:
package com.test.jdbc.main;
import com.test.jdbc.dao.TestDAO;
import com.test.jdbc.dao.impl.TestDAOImpl;
public class Main {
public static void main(String[] args){
TestDAO testDAO=new TestDAOImpl();
Integer usrId=1;
testDAO.getUsrInfoWithC3P0(usrId);
}
}
运行之后显示以下结果,说明我们的c3p0调用成功:
Name:g21121
3.c3p 0与Spring 结合:
数据库连接池最常用的一种模式就是与Spring 或其他ORM 框架结合,这里讲解一下c3p0 与Spring 的结合,其他情况代码类似,大家可以自己研究下。
(1) 下载c3p0 与Spring (http://www.springsource.org/spring-framework/)。
(2) 导入c3p0 与Spring 相关jar 包到classpath 或eclipse 的Build Path 中。
(3) 新建一个属性文件jdbc.properties,其内容为:
#Required(必须) #oracle驱动 #datasource.driverClass=oracle.jdbc.driver.OracleDriver #oracle连接地址 #jdbc:oracle:thin:@192.168.0.14:1521:test #MySQL驱动 datasource.driverClassName=com.mysql.jdbc.Driver #MySQL连接地址 datasource.url=jdbc\:mysql\://192.168.0.14\:3306/test #数据库用户 datasource.user=g21121 #该用户密码 datasource.password=123456 #Optional(可选),以下属性值为参考值,需要根据具体情况去设置 #连接池中保留的最小连接数 datasource.minPoolSize=1 #连接池中保留的最大连接数,默认:15 datasource.maxPoolSize=50 #最大空闲时间,1800秒内未使用则连接被丢弃。为0则永不丢弃,默认: 0 datasource.maxIdleTime=25000 #当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认: 3 datasource.acquireIncrement=2 #JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。默认: 0 datasource.maxStatements=0 #初始化时获取连接数,取值应在minPoolSize与maxPoolSize之间。默认: 3 datasource.initialPoolSize=2 #检查所有连接池中的空闲连接的时间间隔。单位:秒,默认: 0 datasource.idleConnectionTestPeriod=2500 #从数据库获取连接失败后重复尝试的次数。默认: 30 datasource.acquireRetryAttempts=30 #获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认: false datasource.breakAfterAcquireFailure=false #如果为true那么在每个connection提交的时候都将校验其有效性。这样会消耗一定的性能,请酌情处理。建议使用idleConnectionTestPeriod或automaticTestTable等方法来提升连接测试的性能。默认: false datasource.testConnectionOnCheckout=false #两次连接中间隔时间。单位毫秒,默认: 1000 datasource.acquireRetryDelay=1000 #连接关闭时默认将所有未提交的操作回滚。默认: false datasource.autoCommitOnClose=false #c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试使用。默认: null datasource.automaticTestTable=Test #当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。默认: 0 datasource.checkoutTimeout=100 #指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可,默认: null datasource.factoryClassLocation=null #此属性为true将导致大量bug的产生,所以不建议使用 datasource.forceIgnoreUnresolvedTransactions=false #定义了连接池内单个连接所拥有的最大缓存statements数。默认: 0 datasource.maxStatementsPerConnection=0 #c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能通过多线程实现多个操作同时被执行。默认: 3 datasource.numHelperThreads=3 #当用户调用getConnection()时使用哪个用户成为去获取连接的用户。主要用于连接池连接非c3p0的数据源时。默认: null datasource.overrideDefaultUser=name #overrideDefaultUser的密码。默认: null datasource.overrideDefaultPassword=pass #定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:测试的表必须在初始数据源的时候就存在。默认: null datasource.preferredTestQuery=select id from test where id=1 #用户修改系统配置参数执行前最多等待时间。单位:秒,默认: 300 datasource.propertyCycle=300 #如果设为true那么在取得连接的同时将校验连接的有效性。默认: false datasource.testConnectionOnCheckin=true
属性文件中的属性并不是所有的都会用到,可以根据项目自身情况酌情选择。
(4) 在Spring配置文件中加入以下内容:
<!-- spring加载资源文件 --> <bean name="propertiesConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> </list> </property> </bean> <!-- 数据源配置 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${datasource.driverClassName}" /> <property name="jdbcUrl" value="${datasource.url}" /> <property name="user" value="${datasource.user}" /> <property name="password" value="${datasource.password}" /> <property name="minPoolSize" value="${datasource.minPoolSize}" /> <property name="maxPoolSize" value="${datasource.maxPoolSize}" /> <property name="maxIdleTime" value="${datasource.maxIdleTime}" /> <property name="acquireIncrement" value="${datasource.acquireIncrement}" /> <property name="maxStatements" value="${datasource.maxStatements}" /> <property name="initialPoolSize" value="${datasource.initialPoolSize}" /> <property name="idleConnectionTestPeriod" value="${datasource.idleConnectionTestPeriod}" /> <property name="acquireRetryAttempts" value="${datasource.acquireRetryAttempts}" /> <property name="breakAfterAcquireFailure" value="${datasource.breakAfterAcquireFailure}" /> <property name="testConnectionOnCheckout" value="${datasource.testConnectionOnCheckout}" /> </bean>
接下来就可以将dataSource 注入到sessiongFactory,sqlMapClient 等需要的地方了。