开源数据库连接池之C3P0
本篇介绍几种开源数据库连接池,同时重点讲述如何使用C3P0数据库连接池。
之前的博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式。这样能减少数据库创建连接的消耗。正是由于数据库连接池的思想非常重要,所以市面上也有很多开源的数据库连接池供我们使用。主要有以下三个:
DBCP数据库连接池
C3P0 数据库连接池
Tomcat内置的数据库连接池(DBCP)
本篇主要讲述C3P0数据库连接池的使用,关于另外两个数据库连接池的用法请看《开源数据库连接池之DBCP》 、《开源数据库连接池之Tomcat内置连接池》 。如果我们使用这些开源的数据库连接池,我们就可以省略像前一篇博客中自己创建数据库连接池的步骤,这样会省略我们很多事。
C3P0的官网是http://sourceforge.net/projects/c3p0/?source=navbar ,比较不好找。
C3P0实现了连接池和JNDI的绑定,支持JDBC3规范和JDBC2的标准扩展。C3P0与DBCP的区别在于DBCP没有自动回收空闲连接的功能,而C3P0却有。但是C3P0在从连接池中获取和返回连接对象的时候,采用了异步处理方式(即非线程安全,关于异步可以看这篇很好的文章http://www.cnblogs.com/xiohao/p/4385508.html )。
要想了解更多关于C3P0概念的信息,可以通过下载的C3P0的包中的【doc】目录下的index.html来查看关于C3P0的一些信息:
这里面有一些很有帮助的文档,例如快速入门(QuickStart)等等,这里就简单介绍一下:
要使用C3P0同样需要下载其jar包,在C3P0的jar包中共有三个jar包,如下图所示:
如果使用的是非Oracle数据库,则只需导入c3p0-0.9.5.2jar包和mechange-commons-java-0.2.11.jar包即可,如果是使用Oracle数据库的话,还需要导入c3p0-oracle-thin-extras-0.9.5.2.jar包。
C3P0可以有两种使用方法,一种是直接在程序中以调用ComboPooledDataSource对象的一系列方法配置各种数据库和连接池的参数,另一种也是跟DBCP一样使用配置文件来初始化数据库和连接池。
例1:使用第一种方式来简单创建C3P0数据库连接池
在本例中我们仅使用C3P0的连接池类ComboPooledDataSource的对象来设置各个数据库驱动和连接池的参数,这种方法无需配置文件,换句话说也就是在程序中“写死”各个配置信息。
创建一个工程,因为我们使用的是MySQL数据库,因此只需要导入C3P0中的两个jar包即可,当然别忘了还有MySQL的数据库驱动jar包:
同前一篇博客一样,我们现在是使用数据库连接池来获取连接了,而不是通过数据库直接提供的连接,因此《JDBC操作数据库的学习(2)》中的数据库工具类JdbcUtils的部分方法已经不适用了,现在我们重新在刚建的工程中编写一个新的JdbcUtils工具类:
public class JdbcUtils {
private static ComboPooledDataSource ds = null;
static{
try {
ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver"); //为C3P0配置MySQL数据库驱动
ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcdemo"); //为C3P0配置MySQL数据库URL
ds.setUser("root");
ds.setPassword("root");
ds.setMaxPoolSize(50); //设置连接池最大连接数
ds.setMinPoolSize(5); //设置连接池最小连接数
ds.setInitialPoolSize(10); //设置连接池初始化连接数 } catch (PropertyVetoException e) {
throw new ExceptionInInitializerError(e);
}
} public static Connection getConnection() throws SQLException {
return ds.getConnection(); //使用ComboPooledDataSource对象获取连接
} public static void release(Connection conn,Statement st,ResultSet rs) {
if(rs!=null) {
try{
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(st!=null) {
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null) {
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
在上面的代码中,在该工具类一加载进内存时就利用C3P0的连接池类ComboPooledDataSource的对象来设置各个数据库驱动和连接池的参数,例如上面我们设置了数据库连接驱动、数据库URL、数据库用户名和密码、连接池里的最大和最小连接数,连接池初始化时的连接数等等,当然上面的配置只是ComboPooledDataSource对象中设置方法的冰山一角,我们还可以通过ComboPooledDataSource对象的方法为我们的连接池设置更多的功能和参数。
而我们要给别的想操作数据库的方法返回的连接即使通过ComboPooledDataSource对象的getConnection()方法取得的Connection对象,另外通过释放资源的方法还是和以前一模一样,尤其是调用了Connection对象的close方法就能知道,这个Connection对象必定经过C3P0进行功能增强,将数据库直接提供的Connection对象的close方法进行了覆写,才能使我们释放资源时(调用Connection对象的close方法)不会将连接销毁,而是重新放入C3P0的连接池中。
下面我们将通过一个测试代码来看看通过C3P0连接池获得的Connection对象:
public void testConnection() throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null; try{
conn = JdbcUtils.getConnection();
System.out.println(conn);
System.out.println(conn.getClass().getName());
}finally{
JdbcUtils.release(conn, st, rs);
}
}
在控制台上显示的效果如下:
红字信息是因为C3P0在创建数据库连接池时会通过日志来记录其工作的一些信息,我们也可以通过这个信息来查看C3P0创建的连接池的情况。
最后两行是我们通过上面的测试代码打印出来的Connection对象的信息,可以看到C3P0也将数据库驱动直接提供的Connection对象进行了功能增强,而这种增强方式是通过动态代理方式来覆写了原来Connection对象的close方法再返回给我们的,以使我们在释放资源时能将连接重新返回到C3P0的连接池中。
例2:使用第二种方式来简单创建C3P0数据库连接池
和第一种方式不同,在本例中我们使用配置文件的方式使C3P0能配置我们的数据库驱动和连接池所需要的参数。这种方式的好处就是不会在程序里将这些参数“写死”。
C3P0的配置文件里使用什么参数关键字呢?配置文件有没特殊的命名方式呢?配置文件需要放置在什么特别的地方吗?这三个问题是使用C3P0连接池第二种方式必须要知道的。
先说配置文件里使用的参数关键字,这个可以由ComboPooledDataSource对象中的各种set方法得到,比如这个对象中的setDriverClass方法,那么使用配置文件的话配置数据库驱动类的参数即为driverClass。另一种参看C3P0配置参数的方式就是看上面曾经说过的C3P0的包中【doc】目录下的index.html文档,在这个文档找到附录B(Appendix B:Configuration Files)有如下配置参数:
在这张表的下面还有对每一个参数的各种介绍功能和一些默认值,这里就省略不贴图出来了。
接下来就是配置文件了,和DBCP不一样,C3P0必须使用XML来作为配置文件,而且配置文件名和应该放置的位置都有严格的规定:
首先C3P0的配置文件必须要叫“c3p0-config.xml”,另外根据文档,这个配置文件必须要直接或者以jar包的形式存放在你应用的CLASSPATH路径或者WEB-INF/classes路径(WEB工程)下才行。当然我们知道在MyEclipse上如果将配置文件放在【src】目录中在IED编译运行时会自动将【src】中的文件放置在CLASSPATH路径中,所以我们可以直接将配置文件放在【src】目录里。
而文档也提供了一个配置文件中参数内容的例子:
<c3p0-config>
<default-config>
<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">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property> <user-overrides user="test-user">
<property name="maxPoolSize">10</property>
<property name="minPoolSize">1</property>
<property name="maxStatements">0</property>
</user-overrides> </default-config> <!-- This app is massive! -->
<named-config name="intergalactoApp">
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property> <!-- intergalactoApp adopts a different approach to configuring statement caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property> <!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config>
</c3p0-config>
在官方给出的配置文件例子中,有默认配置和自定义配置两种:
⑴ 如果想用默认配置,则在程序中只要在创建ComboPooledDataSource对象时调用其无参的构造器即可,例如ComboPooledDataSource ds = new ComboPooledDataSource()即是使用默认配置。
⑵ 如果是想使用自定义配置,则在创建ComboPooledDataSource对象时将自定义配置的<named-config>指定的名称作为参数传进ComboPooledDataSource的构造器即可,例如按上图的例子来说ComboPooledDataSource ds = new ComboPooledDataSource(“intergalactoApp”)。因此这个配置文件可以配置多个自定义的参数内容,非常灵活,比如我们可以在一个C3P0配置文件中分别自定义MySQL数据库和Oracle数据库的配置参数。
现在我们开始真正地使用第二种方式来使用C3P0连接池,创建一个工程,因为我们使用的是MySQL数据库,因此只需要导入C3P0中的两个jar包即可,当然别忘了还有MySQL的数据库驱动jar包:
这回我们在【src】目录中放置C3P0的配置文件c3p0-config.xml,内容以文档案例做了修改如下:
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcdemo</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">50</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config> <!-- if you want to use Oracle database -->
<named-config name="oracle">
<property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
<property name="jdbcUrl"> jdbc:oracle:thin:@localhost:1521:jdbcdemo</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">50</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</named-config>
</c3p0-config>
在这个配置文件中,默认配置是使用MySQL数据库,也设置了一个自定义配置可以使用Oracle数据库。
同例1一样,我们也是要改写以前的数据库工具类JdbcUtils,代码如下:
public class JdbcUtils {
private static ComboPooledDataSource ds = null;
static{
try {
ds = new ComboPooledDataSource(); //使用配置文件中的默认配置
// ds = new ComboPooledDataSource("oracle"); 如果要使用Oracle则使用配置文件中的自定义配置 } catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
} public static Connection getConnection() throws SQLException {
return ds.getConnection(); //使用ComboPooledDataSource对象获取连接
} public static void release(Connection conn,Statement st,ResultSet rs) {
if(rs!=null) {
try{
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(st!=null) {
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null) {
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
在这个代码中,通过ComboPooledDataSource获取C3P0的连接池对象,因为我们在创建该对象时没有在构造器中传入参数,因此使用的是默认配置,而我们在配置文件中的默认设置也就是使用MySQL数据库。
当然获取连接的getConnection方法和释放资源的release方法都还和例1 一样,通过连接池对象ComboPooledDataSource获取连接,而释放资源跟以前的代码没有任何区别,说明在释放资源调用Connection对象的close方法时,其实已经是被ComboPooledDataSource返回的另一种Connection对象覆写了close方法。
我们通过下面的代码再来试下通过配置文件的方式使用C3P0的连接好不好使:
public void testConnection() throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null; try{
conn = JdbcUtils.getConnection();
System.out.println(conn);
System.out.println(conn.getClass().getName());
}finally{
JdbcUtils.release(conn, st, rs);
}
}
在控制台效果如下,我们照样从C3P0连接池中获取到了连接:
以上就是我们对开源数据库连接池C3P0的整个学习和使用的过程。如果想对C3P0有更深入的理解,上面说过的文档可以是很好的学习方式。
参考博客:
http://weifly.iteye.com/blog/1227182
开源数据库连接池之C3P0的更多相关文章
- 开源数据库连接池之Tomcat内置连接池
本篇介绍几种开源数据库连接池,同时重点讲述如何使用Tomcat服务器内置的数据库连接池. 之前的博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式.这样能减少数 ...
- 开源数据库连接池之DBCP
本篇介绍几种开源数据库连接池,同时重点讲述如何使用Apache公司的的DBCP数据库连接池. 前面一篇博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式.这样能 ...
- 主流Java数据库连接池分析(C3P0,DBCP,TomcatPool,BoneCP,Druid)
主流数据库连接池 常用的主流开源数据库连接池有C3P0.DBCP.Tomcat Jdbc Pool.BoneCP.Druid等 C3p0: 开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDB ...
- java攻城狮之路--复习JDBC(数据库连接池 : C3P0、DBCP)
复习数据库连接池 : C3P0.DBCP 1.数据库连接池技术的优点: •资源重用: 由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销.在减少系统消耗的基础上,另一方面也增 ...
- JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)
JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/beans)中建立数据库连接 2)进行sql操作 3)断开数据库连接 ...
- 【转】JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)
转自:http://www.cnblogs.com/ysw-go/ JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/ ...
- 数据库连接池(c3p0)
(一)问题的提出: 在使用开发基于数据库的web程序时,传统的数据库使用模式按照以下步骤: 在程序中建立数据库连接 进行sql操作 断开数据库连接 但是,这种模式存在着移动的问题: 传统连接模式每次向 ...
- java之数据库连接池-dbcp&c3p0&dbutils
介绍 因为数据库连接对象的创建比较消耗性能,所以可以在应用程序启动时就在内存中开辟一片空间(集合)存放多个数据库连接对象,后面需要连接时直接从该空间中取而不用新创建:使用完毕后归还连接(将连接重新放回 ...
- [javaEE] 开源数据库连接池
一些开源组织提供了数据源的独立实现: DBCP数据库连接池 C3P0数据库连接池 Apache Tomcat内置的连接池 DBCP连接池 apache提供的连接池实现,需要导入common-dbcp. ...
随机推荐
- Kali Linux 安全渗透教程<第三更>1.2 安全渗透所需工具
了解了渗透測试的概念后.接下来就要学习进行渗透測试所使用的各种工具.在做渗透測试之前.须要先了解渗透所需的工具.渗透測试所需的工具如表1-1所看到的: 表1-1 渗透所需工具 splint unhi ...
- H面试程序(16): 简单选择排序
#include<stdio.h> #include<assert.h> void display(int * a, int n) { assert(a); for(int i ...
- JS+CSS打造三级折叠菜单,自动收缩其它级 js
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0
今天在真机调试低版本系统的时候出现如题类似Layout Max Width在ios 8 之前不适用的问题, 初步估计是autolayout 所导致的 查找资料解决方法如下: 将label下Preffe ...
- gpexpand error:Do not have enough valid segments to start the array.
gpstart error: Do not have enough valid segments to start the array. 这个时候需要检查一下shared_buffers设置改小点,就 ...
- POJ 3528 求三维凸包表面积
也是用模板直接套的题目诶 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include < ...
- 关于QuartusII对ram块的综合
之前在看Altera的官方教程上就有说明,如果我们定义一个reg [`word_w]user_ram[`word_d] ; QuartusII会自动综合成为一个ram—— 当然有一些前提:(后续补充 ...
- bresenham算法的FPGA的实现2
在上一篇里http://www.cnblogs.com/sepeng/p/4045593.html <bresenham算法的FPGA的实现1>已经做了一个整体框架的布局,但是那个程序只是 ...
- Week6(10月17日):周末别忘记运动
Part I:提问 =========================== 1.多对多.一对多关系的数据实体模型,如何创建? 已知汽车4S店需开发一个客户关系管理系统(CRM),请为其中的客户和汽车 ...
- jquery删除动态增加的li
<script type="text/jscript"> //楼主帮你修改调整了下 $(document).ready(function () { $('.zuo li ...