介绍
数据库连接池:数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
Java连接池:在Java中开源的数据库连接池有以下几种 (摘录自百度百科):
1、C3P0:是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
2、Proxool:是一个Java SQL Driver驱动程序,提供了对选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中,完全可配置,快速、成熟、健壮。可以透明地为现存的JDBC驱动程序增加连接池功能。
3、Jakarta DBCP:DBCP是一个依赖Jakartacommons-pool对象池机制的数据库连接池。DBCP可以直接的在应用程序中使用。
4、DDConnectionBroker:是一个简单、轻量级的数据库连接池。
5、DBPool:是一个高效、易配置的数据库连接池。它除了支持连接池应有的功能之外,还包括了一个对象池,使用户能够开发一个满足自己需求的数据库连接池。
1 使用原生JDBC操作
首先需要下载官方的jar包,当前版本为0.9.5.2,
CSDN下载链接:http://download.csdn.net/download/weixin_38187317/10252492
官网下载链接:https://sourceforge.net/projects/c3p0/files/latest/download?source=files
下载,解压后将c3p0-0.9.5.2.jar和mchange-commons-java-0.2.11.jar导入项目
新建项目c3p0Test项目结构如下sqljdbc42.jar为SQLServer的连接驱动,MySql同理,需要自己另外下载添加,或者我发的压缩包也有:
1 在工程的src下新建一个名为c3p0-config.xml,注意该名称不能改变
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<c3p0-config>
<!--默认配置 -->
<default-config>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<!--配置连接池1 SQL Server -->
<named-config name="sqlserver">
<property name="user">test</property>
<property name="password">123</property>
<property name="driverClass">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<property name="jdbcUrl">jdbc:sqlserver://localhost:1433; DatabaseName=test</property>
<!-- 以上的user是数据库的用户,password是数据库的密码,driverClass是SQL Server的数据库驱动,jdbcUrl是连接数据库的url -->
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->
<property name="acquireIncrement">5</property>
<!--初始化时获取十个连接,取值应在minPoolSize与maxPoolSize之间 -->
<property name="initialPoolSize">10</property>
<!--连接池中保留的最小连接数 -->
<property name="minPoolSize">10</property>
<!--连接池中保留的最大连接数 -->
<property name="maxPoolSize">50</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。
所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:0 -->
<property name="maxStatements">20</property>
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
<property name="maxStatementsPerConnection">5</property>
</named-config>
<!--配置连接池2 MySql -->
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/CoupleSpace</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
<!-- 以下为更加详细的配置,可选 -->
<!--acquireIncrement:链接用完了自动增量3个。 -->
<property name="acquireIncrement">3</property>
<!--acquireRetryAttempts:链接失败后重新试30次。 -->
<property name="acquireRetryAttempts">30</property>
<!--acquireRetryDelay;两次连接中间隔1000毫秒。 -->
<property name="acquireRetryDelay">1000</property>
<!--autoCommitOnClose:连接关闭时默认将所有未提交的操作回滚。 -->
<property name="autoCommitOnClose">false</property>
<!--automaticTestTable:c3p0测试表,没什么用。 -->
<property name="automaticTestTable">Test</property>
<!--breakAfterAcquireFailure:出错时不把正在提交的数据抛弃。 -->
<property name="breakAfterAcquireFailure">false</property>
<!--checkoutTimeout:100毫秒后如果sql数据没有执行完将会报错,如果设置成0,那么将会无限的等待。 -->
<property name="checkoutTimeout">100</property>
<!--connectionTesterClassName:通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全路径。Default:
com.mchange.v2.c3p0.impl.DefaultConnectionTester -->
<property name="connectionTesterClassName"></property>
<!--factoryClassLocation:指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可。 -->
<property name="factoryClassLocation">null</property>
<!--forceIgnoreUnresolvedTransactions:作者强烈建议不使用的一个属性。 -->
<property name="forceIgnoreUnresolvedTransactions">false</property>
<!--idleConnectionTestPeriod:每60秒检查所有连接池中的空闲连接。 -->
<property name="idleConnectionTestPeriod">60</property>
<!--initialPoolSize:初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。 -->
<property name="initialPoolSize">3</property>
<!--maxIdleTime:最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。 -->
<property name="maxIdleTime">60</property>
<!--maxPoolSize:连接池中保留的最大连接数。 -->
<property name="maxPoolSize">15</property>
<!--maxStatements:最大链接数。 -->
<property name="maxStatements">100</property>
<!--maxStatementsPerConnection:定义了连接池内单个连接所拥有的最大缓存statements数。Default:
0 -->
<property name="maxStatementsPerConnection"></property>
<!--numHelperThreads:异步操作,提升性能通过多线程实现多个操作同时被执行。Default: 3 -->
<property name="numHelperThreads">3</property>
<!--overrideDefaultUser:当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0的数据源时。Default:
null -->
<property name="overrideDefaultUser">root</property>
<!--overrideDefaultPassword:与overrideDefaultUser参数对应使用的一个参数。Default: null -->
<property name="overrideDefaultPassword">password</property>
<!--password:密码。Default: null -->
<property name="password"></property>
<!--preferredTestQuery:定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意: 测试的表必须在初始数据源的时候就存在。Default:
null -->
<property name="preferredTestQuery">select id from test where id=1</property>
<!--propertyCycle:用户修改系统配置参数执行前最多等待300秒。Default: 300 -->
<property name="propertyCycle">300</property>
<!--testConnectionOnCheckout:因性能消耗大请只在需要的时候使用它。Default: false -->
<property name="testConnectionOnCheckout">false</property>
<!--testConnectionOnCheckin:如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->
<property name="testConnectionOnCheckin">true</property>
<!--user:用户名。Default: null -->
<property name="user">root</property>
<!--usesTraditionalReflectiveProxies:动态反射代理。Default: false -->
<property name="usesTraditionalReflectiveProxies">false</property>
</named-config>
<!--配置连接池3 -->
<!--配置连接池4 -->
</c3p0-config>
参数写的注释非常详细了,有很多可选参数,可以同时配置多个连接池,一个连接池对应一个数据库比如这里是Mysql和SQLServer
2 获取连接工具类:
package test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Utils {
// 通过标识名来创建相应连接池
static ComboPooledDataSource dataSource = new ComboPooledDataSource("sqlserver");
// 从连接池中取用一个连接
public static Connection getConnection() throws Exception {
try {
return dataSource.getConnection();
} catch (Exception e) {
System.out.println("Exception in C3p0Utils!"+ e);
throw new Exception("数据库连接出错!"+ e);
}
}
// 释放连接回连接池
public static void close(Connection conn, PreparedStatement pst, ResultSet rs) throws Exception {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
System.out.println("Exception in C3p0Utils!"+ e);
throw new Exception("数据库连接关闭出错!"+ e);
}
}
if (pst != null) {
try {
pst.close();
} catch (SQLException e) {
System.out.println("Exception in C3p0Utils!"+ e);
throw new Exception("数据库连接关闭出错!"+ e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("Exception in C3p0Utils!"+ e);
throw new Exception("数据库连接关闭出错!"+ e);
}
}
}
// 释放连接回连接池
public static void close(Connection conn,ResultSet rs) throws Exception {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
System.out.println("Exception in C3p0Utils!"+ e);
throw new Exception("数据库连接关闭出错!"+ e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("Exception in C3p0Utils!"+ e);
throw new Exception("数据库连接关闭出错!"+ e);
}
}
}
}
3 测试程序:
package test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class C3p0Test {
public static void main(String[] args) {
System.out.println("c3p0连接测试程序");
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = C3p0Utils.getConnection();
st = conn.createStatement();
rs = st.executeQuery("select * from person");
while (rs.next()) {
System.out.println("数据库数据:"+rs.getString("username"));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (rs != null)
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (st != null)
try {
st.close();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
C3p0Utils.close(conn, rs);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
运行结果:
2 c3p0在Hibernate的使用
hibernate内置一个连接池,所有的数据库连接都是从连接池中获取的。SessionFactory加载时会初始化连接池,Hibernate内置的连接池比较简单,效率有限,仅仅用于学习和演示目的,实际使用中最好使用第三方连接池,例如c3p0。覆盖hibernate.connection.pool_size,便能关闭hibernate内置的连接池。
c3p0在hibernate的lib包里附带,不需要自己引入,只要在hibernate参数里设置hibernate.c3p0.*参数,hibernate就自动使用c3p0作为连接池实现如:
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property> <!-- 指定使用SQL Server数据库格式的sql -->
<property name="connection.password">123</property>
<property name="connection.username">test</property>
<property name="connection.url">jdbc:sqlserver://localhost:1433; DatabaseName=test</property>
<property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<!-- 配置使用c3p0第三方连接池 -->
<property name="c3p0.min_size">5</property>
<property name="c3p0.min_size">20</property>
<property name="c3p0.timeout">1800</property>
<property name="c3p0.max_statements">50</property>
<!-- 指定在控制台打印生成的sql -->
<property name="show_sql">true</property>
<!-- 指定hibernate启动时自动创建表结构 注意:使用create会在第一次编译jsp时重新新建表,如果存在会被删除重建-->
<!-- <property name="hbm2ddl.auto">create</property> -->
<!-- 要加这一句,否则可能会遇到异常 JBOSS添加jta,Tomcat添加thread-->
<property name="current_session_context_class">thread</property>
<!-- 指定Cat类为hibernate实体类 -->
<mapping class="bean.Cat"/>
<!-- 下面是使用xml文件配置实体类映射 -->
<!-- <mapping resource="Cat.hbm.xml"/> -->
</session-factory>
</hibernate-configuration>
3 c3p0在Spring的使用
使用也非常简单如果使用JdbcDaoSupport的话,只要将数据源的实现类由BasicDataSource改为ComboPooledDataSource即可,例如:
<!-- 配置C3P0连接池: -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="jdbcUrl" value="jdbc:sqlserver://localhost:1433; DatabaseName=test" />
<property name="user" value="test"></property>
<property name="password" value="123"></property>
</bean>