数据库链接池C3P0学习

c3p0的配置方式分为三种,分别是
1.setters一个个地设置各个配置项
2.类路径下提供一个c3p0.properties文件
3.类路径下提供一个c3p0-config.xml文件html

1.setters一个个地设置各个配置项
这种方式最繁琐,形式通常是这样:java

01	Properties props = new Properties();
02	InputStream in = ConnectionManager.class.getResourceAsStream("/c3p0.properties");
03	props.load(in);
04	in.close();
05	
06	ComboPooledDataSource cpds = new ComboPooledDataSource();
07	cpds.setDriverClass(props.getProperty("driverClass"));
08	cpds.setJdbcUrl(props.getProperty("jdbcUrl"));
09	cpds.setUser(props.getProperty("user"));
10	cpds.setPassword(props.getProperty("password"));

由于繁琐,因此很不适合采用,因而文档提供了另外另种方式。mysql

2. 类路径下提供一个c3p0.properties文件 
文件的命名必须是c3p0.properties,里面配置项的格式为:spring

1	c3p0.driverClass=com.mysql.jdbc.Driver
2	c3p0.jdbcUrl=jdbc:mysql://localhost:3306/jdbc
3	c3p0.user=root
4	c3p0.password=java


上面只提供了最基本的配置项,其余配置项参照 文档配置,记得是c3p0.后面加属性名就是了,最后初始化数据源的方式就是这样简单: sql

1	private static ComboPooledDataSource ds = new ComboPooledDataSource();
2	     
3	public static Connection getConnection() {
4	    try {
5	        return ds.getConnection();
6	    } catch (SQLException e) {
7	        throw new RuntimeException(e);
8	    }
9	}

 

3.类路径下提供一个c3p0-config.xml文件  
这种方式使用方式与第二种差很少,可是有更多的优势 
(1).更直观明显,很相似hibernate和spring的配置 
(2).能够为多个数据源服务,提供default-config和named-config两种配置方式 
下面是一个配置模板: 数据库

01	<c3p0-config>
02	  <default-config>  
03	    <property name="user">root</property>
04	    <property name="password">java</property>
05	    <property name="driverClass">com.mysql.jdbc.Driver</property>
06	    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc</property>
07	     
08	    <property name="initialPoolSize">10</property>
09	    <property name="maxIdleTime">30</property>
10	    <property name="maxPoolSize">100</property>
11	    <property name="minPoolSize">10</property>
12	  </default-config>
13	   
14	  <named-config name="myApp">
15	    <property name="user">root</property>
16	    <property name="password">java</property>
17	    <property name="driverClass">com.mysql.jdbc.Driver</property>
18	    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc</property>
19	     
20	    <property name="initialPoolSize">10</property>
21	    <property name="maxIdleTime">30</property>
22	    <property name="maxPoolSize">100</property>
23	    <property name="minPoolSize">10</property>
24	  </named-config>
25	</c3p0-config>

 

若是要使用default-config则初始化数据源的方式与第二种同样,若是要使用named-config里面配置初始化数据源,则只要使用一个带参数的ComboPooledDataSource构造器就能够了 缓存

private static ComboPooledDataSource ds = new ComboPooledDataSource("myApp");

 

下面整理一下从文档和网上学习到的c3p0配置的理解 (user,password,driverClass,jdbcUrl没有说的必要) 服务器

1.基本配置项网络

01	acquireIncrement
02	default : 3
03	链接池在无空闲链接可用时一次性建立的新数据库链接数
04	
05	initialPoolSize
06	default : 3
07	链接池初始化时建立的链接数
08	
09	maxPoolSize
10	default : 15
11	链接池中拥有的最大链接数,若是得到新链接时会使链接总数超过这个值则不会再获取新链接,而是等待
12	其余链接释放,因此这个值有可能会设计地很大
13	
14	maxIdleTime
15	default : 0 单位 s
16	链接的最大空闲时间,若是超过这个时间,某个数据库链接尚未被使用,则会断开掉这个链接
17	若是为0,则永远不会断开链接
18	
19	minPoolSize
20	default : 3
21	链接池保持的最小链接数,后面的maxIdleTimeExcessConnections跟这个配合使用来减轻链接池的负载

2.管理链接池的大小和链接的生存时间ide

01	maxConnectionAge
02	default : 0 单位 s
03	配置链接的生存时间,超过这个时间的链接将由链接池自动断开丢弃掉。固然正在使用的链接不会立刻断开,而是等待
04	它close再断开。配置为0的时候则不会对链接的生存时间进行限制。
05	
06	maxIdleTimeExcessConnections
07	default : 0 单位 s
08	这个配置主要是为了减轻链接池的负载,好比链接池中链接数由于某次数据访问高峰致使建立了不少数据链接
09	可是后面的时间段须要的数据库链接数不多,则此时链接池彻底没有必要维护那么多的链接,因此有必要将
10	断开丢弃掉一些链接来减轻负载,必须小于maxIdleTime。配置不为0,则会将链接池中的链接数量保持到minPoolSize。
11	为0则不处理。


maxIdleTime也能够归属到这一类,前面已经写出来了。

3.配置链接测试:由于链接池中的数据库链接颇有多是维持数小时的链接,颇有可能由于数据库服务器的问题,网络问题等致使实际链接已经无效,可是链接池里面的链接仍是有效的,若是此时得到链接确定会发生异常,因此有必要经过测试链接来确认链接的有效性。
下面的前三项用来配置如何对链接进行测试,后三项配置对链接进行测试的时机。

01	automaticTestTable
02	default : null
03	用来配置测试链接的一种方式。配置一个表名,链接池根据这个表名建立一个空表,
04	而且用本身的测试sql语句在这个空表上测试数据库链接
05	这个表只能由c3p0来使用,用户不能操做,同时用户配置的preferredTestQuery 将会被忽略。
06	
07	preferredTestQuery
08	default : null
09	用来配置测试链接的另外一种方式。与上面的automaticTestTable两者只能选一。
10	若是要用它测试链接,千万不要设为null,不然测试过程会很耗时,同时要保证sql语句中的表在数据库中必定存在。
11	
12	connectionTesterClassName
13	default :  com.mchange.v2.c3p0.impl.DefaultConnectionTester
14	链接池用来支持automaticTestTable和preferredTestQuery测试的类,必须是全类名,就像默认的那样,
15	能够经过实现UnifiedConnectionTester接口或者继承AbstractConnectionTester来定制本身的测试方法
16	
17	idleConnectionTestPeriod
18	default : 0
19	用来配置测试空闲链接的间隔时间。测试方式仍是上面的两种之一,能够用来解决MySQL8小时断开链接的问题。由于它
20	保证链接池会每隔必定时间对空闲链接进行一次测试,从而保证有效的空闲链接能每隔必定时间访问一次数据库,将于MySQL
21	8小时无会话的状态打破。为0则不测试。
22	
23	testConnectionOnCheckin
24	default : false
25	若是为true,则在close的时候测试链接的有效性。为了提升测试性能,能够与idleConnectionTestPeriod搭配使用,
26	配置preferredTestQuery或automaticTestTable也能够加快测试速度。
27	
28	testConnectionOnCheckout
29	default : false
30	性能消耗大。若是为true,在每次getConnection的时候都会测试,为了提升性能,
31	能够与idleConnectionTestPeriod搭配使用,
32	配置preferredTestQuery或automaticTestTable也能够加快测试速度。


4.配置PreparedStatement缓存 

01	maxStatements
02	default : 0
03	链接池为数据源缓存的PreparedStatement的总数。因为PreparedStatement属于单个Connection,因此
04	这个数量应该根据应用中平均链接数乘以每一个链接的平均PreparedStatement来计算。为0的时候不缓存,
05	同时maxStatementsPerConnection的配置无效。
06	
07	maxStatementsPerConnection
08	default : 0
09	链接池为数据源单个Connection缓存的PreparedStatement数,这个配置比maxStatements更有意义,由于
10	它缓存的服务对象是单个数据链接,若是设置的好,确定是能够提升性能的。为0的时候不缓存。

5.重连相关配置 

01	acquireRetryAttempts
02	default : 30
03	链接池在得到新链接失败时重试的次数,若是小于等于0则无限重试直至链接得到成功
04	
05	acquireRetryDelay
06	default : 1000 单位ms
07	链接池在得到新链接时的间隔时间
08	
09	breakAfterAcquireFailure
10	default : false
11	若是为true,则当链接获取失败时自动关闭数据源,除非从新启动应用程序。因此通常不用。


我的以为上述三个没有更改的必要,但能够将acquireRetryDelay配置地更短一些

 

6.定制管理Connection的生命周期

1	connectionCustomizerClassName
2	default : null
3	用来定制Connection的管理,好比在Connection acquire 的时候设定Connection的隔离级别,或者在
4	Connection丢弃的时候进行资源关闭,就能够经过继承一个AbstractConnectionCustomizer来实现相关
5	方法,配置的时候使用全类名。有点相似监听器的做用。


例如: 

01	import java.sql.Connection;
02	import com.mchange.v2.c3p0.AbstractConnectionCustomizer;
03	
04	public class ConnectionCustomizer extends AbstractConnectionCustomizer{
05	
06	    @Override
07	    public void onAcquire(Connection c, String parentDataSourceIdentityToken)
08	            throws Exception {
09	        System.out.println("acquire : " + c);
10	    }
11	    @Override
12	    public void onCheckIn(Connection c, String parentDataSourceIdentityToken)
13	            throws Exception {
14	        System.out.println("checkin : " + c);
15	    }
16	    @Override
17	    public void onCheckOut(Connection c, String parentDataSourceIdentityToken)
18	            throws Exception {
19	        System.out.println("checkout : " + c);
20	    }
21	    @Override
22	    public void onDestroy(Connection c, String parentDataSourceIdentityToken)
23	            throws Exception {
24	        System.out.println("destroy : " + c);
25	    }
26	}

 

<property name="connectionCustomizerClassName">liuyun.zhuge.db.ConnectionCustomizer</property>

 

7.配置未提交的事务处理 

1	autoCommitOnClose
2	default : false
3	链接池在回收数据库链接时是否自动提交事务
4	若是为false,则会回滚未提交的事务
5	若是为true,则会自动提交事务
6	
7	forceIgnoreUnresolvedTransactions
8	default : false
9	这个配置强烈不建议为true。

8.配置debug和回收Connection通常来讲事务固然由本身关闭了,为何要让链接池来处理这种不细心问题呢?

01	unreturnedConnectionTimeout
02	default : 0 单位 s
03	为0的时候要求全部的Connection在应用程序中必须关闭。若是不为0,则强制在设定的时间到达后回收
04	Connection,因此必须当心设置,保证在回收以前全部数据库操做都可以完成。这种限制减小Connection未关闭
05	状况的不是很适用。为0不对connection进行回收,即便它并无关闭。
06	
07	debugUnreturnedConnectionStackTraces
08	default : false
09	若是为true而且unreturnedConnectionTimeout设为大于0的值,当全部被getConnection出去的链接
10	unreturnedConnectionTimeout时间到的时候,就会打印出堆栈信息。只能在debug模式下适用,由于
11	打印堆栈信息会减慢getConnection的速度

同第七项同样的,链接用完固然得close了,不要经过unreturnedConnectionTimeout让链接池来回收未关闭的链接。

9.其余配置项:由于有些配置项几乎没有本身配置的必要,使用默认值就好,因此没有再写出来

1	checkoutTimeout
2	default : 0
3	配置当链接池全部链接用完时应用程序getConnection的等待时间。为0则无限等待直至有其余链接释放
4	或者建立新的链接,不为0则当时间到的时候若是仍没有得到链接,则会抛出SQLException

3、示例:

示例采用第二种方式:

1.c3p0.properties:

 

#驱动  
c3p0.driverClass=com.mysql.jdbc.Driver  
#地址  
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/jdbc  
#用户名  
c3p0.user=root  
#密码  
c3p0.password=lovejava  
#-------------------------------  
#链接池初始化时建立的链接数  
c3p0.initialPoolSize=3  
#链接池保持的最小链接数  
c3p0.minPoolSize=3  
#链接池在无空闲链接可用时一次性建立的新数据库链接数,default:3  
c3p0.acquireIncrement=3  
#链接池中拥有的最大链接数,若是得到新链接时会使链接总数超过这个值则不会再获取新链接,而是等待其余链接释放,因此这个值有可能会设计地很大,default : 15  
c3p0.maxPoolSize=15  
#链接的最大空闲时间,若是超过这个时间,某个数据库链接尚未被使用,则会断开掉这个链接,单位秒  
c3p0.maxIdleTime=100  
#链接池在得到新链接失败时重试的次数,若是小于等于0则无限重试直至链接得到成功  
c3p0.acquireRetryAttempts=30  
#链接池在得到新链接时的间隔时间  
c3p0.acquireRetryDelay=1000

 

 

 2.ConnectionPool

 

package com.study.pool;  
  
import java.sql.Connection;  
import java.sql.SQLException;  
  
import javax.sql.DataSource;  
  
import com.mchange.v2.c3p0.ComboPooledDataSource;  
  
public class ConnectionPool {  
    private DataSource ds;  
    private static ConnectionPool pool;  
    private ConnectionPool(){  
        ds = new ComboPooledDataSource();  
    }  
    public static final ConnectionPool getInstance(){  
        if(pool==null){  
            try{  
                pool = new ConnectionPool();  
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
        return pool;  
    }  
    public synchronized final Connection getConnection() {    
        try {  
            return ds.getConnection();  
        } catch (SQLException e) {       
            e.printStackTrace();  
        }  
        return null;  
    }  
      
}

 

 

 3.PoolThread

 

package com.study.pool;  
  
import java.sql.Connection;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
  
public class PoolThread extends Thread {  
    @Override  
    public void run(){  
        ConnectionPool pool = ConnectionPool.getInstance();  
        Connection con = null;  
        PreparedStatement stmt= null;  
        ResultSet rs = null;  
        try{  
            con = pool.getConnection();  
            stmt = con.prepareStatement("select sysdate as nowtime from dual");  
            rs = stmt.executeQuery();  
            while(rs.next()){  
                System.out.println(Thread.currentThread().getId()+"---------------开始"+rs.getString("nowtime"));  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }finally{  
            try {  
                rs.close();  
                stmt.close();  
                con.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
        System.out.println(Thread.currentThread().getId()+"--------结束");  
    }  
}

 

 4.PoolMain

 

package com.study.pool;  
  
public class PoolMain {  
  
    /** 
     * 数据源缓冲池 实例练习 
     */  
    public static void main(String[] args) {  
        System.out.println("缓冲池模拟开始");  
        PoolThread[] threads = new PoolThread[50];  
        for(int i=0;i<threads.length;i++){  
            threads[i] = new PoolThread();  
        }  
        for(int i=0;i<threads.length;i++){  
            threads[i].start();  
        }  
    }  
  
}
相关文章
相关标签/搜索