首页 > 代码库 > 功能第二篇——数据源之C3P0数据源(JDBC)
功能第二篇——数据源之C3P0数据源(JDBC)
综述
C3P0由三部分内容组成。实例化对象,各配置项的含义,以及加载配置项的方式。
实例化对象的方式有三种,第一种方式直接new ComboPooledDataSource,第二种方式使用工厂类DataSources.poolDataSource方法。第三种不常见。第一种方式是最方便的方式。
C3P0的配置项主要有:
- 连接数据库的必要属性:例如jdbcUrl,user,password等。
- 连接池的大小配置。例如initialPoolSize
- 连接对象的生命周期。例如maxConnectionAge。
- 测试连接的配置,例如preferredTestQuery指定测试SQL语句。
- 重连策略的配置,例如acquireRetryAttempts指定重连次数。
- statement对象的配置,例如maxStatements指定最大Statement的总数。
- 线程配置,例如numHelperThread指定连接池拥有的线程数量。
- 事务配置,例如autoCommitOnClose指定是否在回收连接对象时自动提交事务。
- 调试模式,例如debugUnreturnedConnectionStackTraces为true时,会打印所有从连接池获取连接对象的记录。
- 监听类的设置,例如connectionCustomizerClassName指定监听类的名称,该类可以实现onAcquire,onDestory等方法。
- 日志的设置,例如com.mchange.v2.log.MLog指定日志的实现方式。常见的有log4J,commonLogging等。
配置项常见的加载方式有三种:
- 代码方式:通过实例对象调用setXX方法。
- properties文件:这种方式需要properties文件的名称必须为c3p0.properties,而且该文件必须在类加载路径下。
- xml文件:这种方式需要文件名称为c3p0-config.xml,路径由com.mchange.v2.c3p0.cfg.xml指定。
实例化
实例化ComboPooledDataSource
1 // 创建实例,dataSourceName指定数据源的名称 2 ComboPooledDataSource dataSource = new ComboPooledDataSource(dataSourceName); 3 // 设置数据库url 4 dataSource.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:masteroracle"); 5 // 设置数据库驱动类 6 dataSource.setDriverClass("oracle.jdbc.driver.OracleDriver"); 7 // 设置用户名 8 dataSource.setUser("system"); 9 // 设置密码 10 dataSource.setPassword("password"); 11 Connection conn = dataSource.getConnection(); 12 runSQLTest(conn);
工厂DataSources方式
1 // 创建unpooled的数据源 2 DataSource ds_unpooled = DataSources.unpooledDataSource(jdbcUrl, user, password); 3 // pooled数据源的参数 4 Map<String,String> paramMap = new HashMap<>(); 5 DataSource pooled = DataSources.pooledDataSource(ds_unpooled,paramMap); 6 Connection conn = pooled.getConnection(); 7 runSQLTest(conn); 8 conn.close(); 9 DataSources.destroy(pooled); 10 return pooled;
配置项的含义
C3P0各配置项的前缀为c3p0。如果指定dataSourceName,前缀为c3p0.named-configs.dataSourceName。如果存在多个用户,用户可以覆盖默认的配置项,前缀为c3p0.user-overrides.user。
Java代码方式
1 /** -----------------------配置数据源----------------------------- **/ 2 /** 3 * 配置数据源 4 * 5 * @param dataSource 6 * @return 7 * @throws PropertyVetoException 8 */ 9 public static ComboPooledDataSource configDataSource(ComboPooledDataSource dataSource) 10 throws PropertyVetoException { 11 // 连接数据库的必要属性 12 connDatabaseConfig(dataSource,"masterOracle"); 13 // 连接池的相关配置 14 connPoolConfig(dataSource); 15 // 连接对象的生命周期配置 16 connAgeConfig(dataSource); 17 // 测试连接的配置 18 connTestConfig(dataSource); 19 // statement对象的配置 20 statementConfig(dataSource); 21 // 重连配置 22 reconnConfig(dataSource); 23 // 连接的监听类配置 24 connListenerConfig(dataSource); 25 // 事务的配置 26 tranConfig(dataSource); 27 // 调试模式 28 debugMode(dataSource); 29 // 线程配置 30 threadConfig(dataSource); 31 return dataSource; 32 }
连接必要属性
- driverClassName:驱动类的名称,包名+类名
- jdbcUrl:数据库实例的url地址,格式为jdbc:subprotocol:subname。其中subprotocol表示连接方式。
- user:用户名
- password:密码。
C3P0.properties的方式
##-------------------------------数据库连接属性-----------------------------------## # 驱动类名称 c3p0.driverClass=oracle.jdbc.driver.OracleDriver # 数据库实例url地址 c3p0.jdbcUrl=jdbc:oracle:thin:@localhost:1521:masteroracle # 用户名 c3p0.user=system # 密码 c3p0.password=password
代码方式
1 // 设置数据库url 2 dataSource.setJdbcUrl(jdbcUrl); 3 // 设置数据库驱动类 4 dataSource.setDriverClass(driverClassName); 5 // 设置用户名 6 dataSource.setUser(user); 7 // 设置密码 8 dataSource.setPassword(password); 9 // 输出dataSourceName,在初始化ComboPooledDataSource时,字符串参数作为数据源名称, 10 dataSource.getDataSourceName();
连接池大小
- initialPoolSize:连接池的初始需求量大小,实际创建的连接对象小于需求量大小。
- minPoolSize:连接池连接数量的最小值。
- maxPoolSize:连接池连接数量的最大值。
- acquireIncrement:当实际连接不够用时,调整需求量的大小,需求量的递增值。
C3P0.properties的方式
##-------------------------------连接池配置-------------------------------------## # 连接池拥有连接对象的初始值,这种情形下只是Acquire(需求)的初始值,真正创建对象会根据Acquire来按需创建 c3p0.initialPoolSize=10 # 连接池拥有连接对象的最大值,默认值为3 c3p0.maxPoolSize=20 # 连接池拥有连接对象的最小值,默认值为3 c3p0.minPoolSize=5 # 当无空闲连接时,新创建的连接数,默认值为3 c3p0.acquireIncrement=3
代码方式
1 /** 2 * 连接池的配置 initialPoolSize:连接池的初始值 maxPoolSize:连接池的最大值 minPoolSize:连接池的最小值 3 * 4 * @param dataSource 5 */ 6 private static void connPoolConfig(ComboPooledDataSource dataSource) { 7 // 连接池的初始值,默认值为3 8 dataSource.setInitialPoolSize(10); 9 // 连接池的最大值,默认值为0 10 dataSource.setMaxPoolSize(20); 11 // 连接池的最小值,最小值为3 12 dataSource.setMinPoolSize(1); 13 // 连接池的递增值,默认值为3 14 dataSource.setAcquireIncrement(5); 15 }
连接生命周期
- maxIdleTime:空闲连接对象的超时时间,当连接对象处于空闲状态的时间超过此时间,连接池销毁该连接对象。
- maxConnectionAge:连接对象的最大生命值,从创建连接对象开始计算。当超出此时间,销毁连接对象。与maxIdleTime的区别在于maxIdleTime只适用于空闲连接对象,而且是从空闲状态开始计算时间。
- maxIdleTimeExcessConnections:当连接池负载较低时,空闲连接对象的超时时间,设置此项可以在负载较低时,快速的释放链接。
- unreturnedConnectionTimeout:连接对象的最大使用时间。从连接池中获取连接对象开始计算,如果超出此时间,该连接对象还没有被连接池回收,那么连接池创建新连接对象替换旧连接对象。
C3P0.proerties的方式
##-------------------------------连接池中连接对象的生命周期--------------------------## # 连接对象的最大生存时间,起始时间从连接池从数据库中创建连接对象开始计算。0表示永远不销毁 c3p0.maxConnectionAge=0 # 空闲连接对象的超时时间,起始时间从连接对象状态变为空闲时起计算。 c3p0.maxIdleTime=1800 # 当连接池不处于满载状态时,空闲连接对象的最大生存时间,设置此值,可以快速的减少连接池的大小 c3p0.maxIdleTimeExcessConnections=60 # 连接对象回收的超时时间,当连接池无法在一定时间内回收连接对象时,销毁旧对象,重新创建新对象 c3p0.unreturnedConnectionTimeout=600
代码方式
/** * 连接池生命周期配置,连接池首先从数据库中获取连接,用户请求时从连接池中获取连接。默认值为0,表示永不过期。 maxConnectionAge: * 连接对象生命的最大值,超过此时间,连接池会销毁连接对象,连接池变小。单位为秒,建议设置1800或更多 maxIdleTime: * 空闲连接在连接池中的超时时间,超过此时间,连接池将会销毁连接对象。单位为秒,建议设置1800或更多 * maxIdleTimeExcessConnections:当连接池不处于过载状态时,空闲连接对象生命的最大值。 * unreturnedConnectionTimeout:当连接对象在一定时间内无法回收,则创建新连接对象,销毁旧连接对象 * * @param dataSource */ private static void connAgeConfig(ComboPooledDataSource dataSource) { // 连接对象生命的最大值,它指绝对时间。从创建开始时计算,默认值为0 dataSource.setMaxConnectionAge(10 * 60 * 60); // 空闲连接的超时时间,从连接池变为空闲状态开始计算 dataSource.setMaxIdleTime(1800); // 空闲连接对象生命的最大值 dataSource.setMaxIdleTimeExcessConnections(60); // 连接对象的最大使用时间,设置为2小时 dataSource.setUnreturnedConnectionTimeout(2 * 60 * 60); }
测试连接
- automaticTestTable:测试连接使用的数据库表
- connectionTesterClassName:测试连接使用的类名称
- idleConnectionTestPeriod:测试连接的时间间隔,在此间隔内不执行连接测试
- preferredTestQuery:SELECT 1。如果支持JDBC 4,会使用Connection.isAlive方法不设置此值。
- testConnectionOnCheckin:是否在连接池中回收连接对象时进行连接测试,
- testConnectionOnCheckOut:从连接池中取出连接对象时进行连接测试。
C3P0.properties的方式
##-------------------------------测试连接配置项----------------------------------## # 从连接池中获取连接对象时进行连接测试 c3p0.testConnectionOnCheckout=true # 从连接池回收对象时进行连接测试 c3p0.testConnectionOnCheckin=true # 连接测试的间隔,在这一段时间内不进行连接测试 c3p0.idleConnectionTestPeriod=60 # 连接测试时使用的类,设置此值时忽略preferredTestQuery,automaticTestTable等属性值 #c3p0.connectionTesterClassName=com.rain.Tester.ConnectionTesterSample # 测试的SQL语句 c3p0.preferredTestQuery=select 1 # 连接测试时使用的数据库表 c3p0.automaticTestTable=test
代码方式
/** * 连接测试配置。 automaticTestTable:测试连接时使用的数据库表 ,默认值为null。connectionTesterClassName:测试连接时使用的类名称 * idleConnectionTestPeriod:测试连接间隔时间。在此段时间内不进行连接测试。 preferredTestQuery:连接测试使用的SQL语句。默认语句为select * 1 from dual。 testConnectionOnCheckin:从连接池回收连接对象时测试连接。默认值为false * testConnectionOnCheckOut:从连接池取出连接对象时测试连接。默认值为false。 * forceSynchronousCheckins:连接池回收连接对象时是同步,还是异步,默认是异步。默认值为false * * @param dataSource * @throws PropertyVetoException */ private static void connTestConfig(ComboPooledDataSource dataSource) throws PropertyVetoException { // 连接测试使用的数据库表,默认值为Null dataSource.setAutomaticTestTable("dual"); // 连接测试使用的SQL语句,默认使用Connection对象的isAlive方法,所以一般不设置此值,默认值为null dataSource.setPreferredTestQuery("select 1"); // 从连接池取出连接时测试连接,默认值为false dataSource.setTestConnectionOnCheckout(true); // 从连接池回收连接时测试连接,默认值为false。 dataSource.setTestConnectionOnCheckin(true); // 测试连接的间隔时间,默认值为0 dataSource.setIdleConnectionTestPeriod(60); // 测试连接使用的类名称 dataSource.setConnectionTesterClassName("com.rain.Tester.ConnectionTesterSample"); }
重连策略
- acquireRetryAttempts:连接失败后,重连次数
- acquireRetryDelay:第一次重连与第二次重连的时间间隔。单位为毫秒
- checkTimeOut:等待连接的超时时间,超出此时间后不在进行重连。
- breakAfterAcquireFailure:当连接失败后,是否销毁数据源对象,true表示是,false表示否。
C3P0.properties
##-------------------------------重新连接---------------------------------------## # 重新连接的次数 c3p0.acquireRetryAttempts=5 # 重新连接的时间间隔,单位为毫秒 c3p0.acquireRetryDelay=3000 # 等待连接响应的超时时间 c3p0.checkoutTimeout=120 # 当连接失败时,是否销毁数据源对象,true表示是,false表示否 c3p0.breakAfterAcquireFailure=true
代码方式
/** * 当连接失败后,重新连接的配置。 acquireRetryAttempts:重连的次数。 acquireRetryDelay:重连的时间间隔。单位为毫秒 * breakAfterAcquireFailure:重连失败后,如果此值设置为false,数据源对象不会销毁,设置为false。数据源被销毁。 * checkoutTimeout:等待连接响应的时间。 */ private static void reconnConfig(ComboPooledDataSource dataSource) { // 设置重连次数为3,默认值为30 dataSource.setAcquireRetryAttempts(3); // 设置重连的时间间隔为2秒,默认值为1000 dataSource.setAcquireRetryDelay(2000); // 等待连接响应的超时时间。默认值为0表示永远不超时 dataSource.setCheckoutTimeout(4); // 重连失败后,销毁数据源。默认值为false dataSource.setBreakAfterAcquireFailure(true); }
Statement配置
- maxStatements:连接池缓存PreparedStatement对象的总数
- maxStatementsPerConnection:每个连接缓存PreparedStatement的最大值。
- statementCacheNumDeferredCloseThreads:当Connection关闭时,有可能会产生Statement对象没有关闭的情形,此时需要额外线程确保Statement对象在Connection关闭时正在关闭。一般配置为0或1
C3P0.properties的方式
##-------------------------------statement对象相关配置---------------------------## # c3p0拥有的PreparedStatement对象的总数 c3p0.maxStatements=100 # 每个连接拥有PreparedStament对象的数量 c3p0.maxStatementsPerConnection=10 # 当Connection对象关闭时,启动额外线程确保statement对象关闭 # This parameter should only be set if you observe that attempts by c3p0 to close() cached #statements freeze statementCacheNumDeferredCloseThreads=1
代码方式
1 /** 2 * 连接池中PreparedStatement对象的配置 PreparedStatement对象的配置。 maxStatements:连接池拥有PreparedStatement对象的总数。 3 * maxStatementsPerConnections:每个连接拥有PreparedStatement对象的数目。 4 * 5 * @param dataSource 6 */ 7 private static void statementConfig(ComboPooledDataSource dataSource) { 8 // 设置PreparedStatement对象的总数,默认值为0,表示关闭 9 dataSource.setMaxStatements(100); 10 // 设置每个连接拥有Statement对象的数目,默认值为0,表示关闭。 11 dataSource.setMaxStatementsPerConnection(15); 12 }
线程配置
- numHelperThreads:连接池拥有的线程数量。
- maxAdministrativeTaskTime:线程执行任务的超时时间,当超出此时间时,会销毁该线程,重新创建新线程。
- forceSynchronousCheckins:连接池回收连接对象时默认是同步方式执行连接测试,此值设置为true时,连接测试与回收连接对象是异步执行的。
C3P0.properties的方式
##-------------------------------线程池----------------------------------------## # 连接池拥有的线程数量 c3p0.numHelperThreads=5 # 线程执行的最大时间 c3p0.maxAdministrativeTaskTime=600 # 启动独立的线程来在连接被连接池回收阶段进行测试 forceSynchronousCheckins=true
代码方式
1 /** 2 * 连接池的线程设置 numHelperThread:连接池拥有的线程数量 maxAdministrativeTaskTime:线程执行的超时时间。 3 * 4 * @param dataSource 5 */ 6 private static void threadConfig(ComboPooledDataSource dataSource) { 7 // 设置线程数量为10,默认值为3 8 dataSource.setNumHelperThreads(10); 9 // 设置线程的超时时间,默认值为0,设置为5分钟 10 dataSource.setMaxAdministrativeTaskTime(5 * 60); 11 }
事务配置
- autoCommitOnClose:回收连接对象时,是否自动提交事务。默认不配置,通过其他方式管理事务,例如Spring事务
- forceIgnoreUnresolvedTransactions:回收连接对象时,是否强制回滚或者提交事务,默认不配置。
C3P0.properties的方式
##-------------------------------事务-----------------------------------------## # 交给Spring去管理事务,默认不配置这些项 # 连接关闭时,是否自动提交事务 c3p0.autoCommitOnClose=false # 连接回收时,是否强制提交或者回滚当前连接拥有的事务,默认不配置。 c3p0.forceIgnoreUnresolvedTransactions=false
代码方式
1 /** 2 * 连接对象的事务配置 autoCommitOnClose:是否自动提交事务,true为是,false为否,默认为否 forceIgnoreUnresolvedTransactions 3 * 回收连接时,是否强制回滚或提交事务,默认为false。一般不设置此值, 例如由Spring来管理事务 4 * 5 * @param dataSource 6 */ 7 private static void tranConfig(ComboPooledDataSource dataSource) { 8 // 关闭自动提交事务,默认值为false 9 dataSource.setAutoCommitOnClose(false); 10 // 回收连接时,是否强制回滚或提交事务,设置为false。 11 dataSource.setForceIgnoreUnresolvedTransactions(false); 12 13 }
调试模式
- debugUnreturnedConnectionStackTraces:打印从连接池获取连接对象的所有信息。
C3P0.properties的方式
##-------------------------------调试模式--------------------------------------## # 当从连接池获取连接对象时,打印所有信息。 c3p0.debugUnreturnedConnectionStackTraces=true
代码方式
1 /** 2 * 调试模式的设置 debugUnreturnedConnectionStackTraces:从连接池获取连接对象时,打印所有信息 3 4 * 5 * @param dataSource 6 */ 7 private static void debugMode(ComboPooledDataSource dataSource) { 8 // 从连接池获取连接对象时,打印所有信息 9 dataSource.setDebugUnreturnedConnectionStackTraces(true); 10 }
监听类
connectionCustomizerClassName:监听类的名称,监听类继承自AbstractConnectionCustomizer,监听类有四个方法
- onAcquire在数据库中创建连接对象时触发。
- onDestory在连接池中销毁连接对象时触发。
- onCheckOut从连接池获取连接对象时触发
- onCheckIn 从连接池回收连接对象时触发。
C3P0.properties的方式
##-------------------------------监听类---------------------------------------## c3p0.connectionCustomizerClassName=com.rain.Tester.ConnCustomrizerSample
代码方式
1 /** 2 * 设置连接对象的监听类,该类有四个方法 onAcquire:表示当连接池从数据库中获得连接时 onDestory:表示当连接池销毁连接对象时 onCheckOut:从连接池中获取连接对象时 3 * onCheckIn:连接池回收连接对象时。 4 */ 5 private static void connListenerConfig(ComboPooledDataSource dataSource) { 6 // 设置连接对象的监听类 7 dataSource.setConnectionCustomizerClassName("com.rain.Tester.ConnCustomrizerSample"); 8 }
日志配置
- com.mchange.v2.log.MLog:日志的实现方式
- com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL:日志的级别。可选值为OFF,SERVER,WARNING,INFO,FINE,FINER,FINEST,ALL
- com.mchange.v2.log.NameTransformer:日志按每个数据源类输出,还是按包。com.mchange.v2.log.PackageNames表示按包,默认的方式按类的方式
- com.mchange.v2.log.jdk14logging.suppressStackWalk:是否显示哪些类,哪些方法产生的日志,true表示不显示,false表示显示,默认值为true。
C3P0.properties的方式
##-------------------------------日志配置--------------------------------------## # 日志的实现方式 com.mchange.v2.log.MLog=log4j # 日志的级别,OFF,SERVER,WARNING,INFO,FINE,FINER,FINEST,ALL com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL=All # 日志按包输出 com.mchange.v2.log.NameTransformer=com.mchange.v2.log.PackageNames # determine the class and method from which a log message was generated,当为true时,不打印这些日志信息 com.mchange.v2.log.jdk14logging.suppressStackWalk=true
加载配置项的方式
代码方式:通过new实例化dataSource,调用setXX方法。
1 package com.rain.core; 2 3 import java.beans.PropertyVetoException; 4 import java.io.IOException; 5 import java.sql.Connection; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.sql.Statement; 9 import java.util.HashMap; 10 import java.util.Map; 11 import javax.sql.DataSource; 12 import com.mchange.v2.c3p0.ComboPooledDataSource; 13 import com.mchange.v2.c3p0.DataSources; 14 15 public class C3P0DataSourceSample { 16 private static final String masterOraclejdbcUrl = 17 "jdbc:oracle:thin:@localhost:1521:masteroracle"; 18 private static final String orclJdbcUrl = "jdbc:oracle:thin:@localhost:1521:orcl"; 19 private static final String driverClassName = "oracle.jdbc.driver.OracleDriver"; 20 private static final String user = "system"; 21 private static final String password = "password"; 22 23 public static void main(String[] args) throws Exception { 24 // 创建数据源对象 25 ComboPooledDataSource dataSource = createByInitInstance(); 26 // 配置数据源 27 // configDataSource(dataSource); 28 // 打印数据源信息 29 printDataSourceInfo(dataSource); 30 // 运行测试用例 31 runSQLTest(dataSource); 32 } 33 34 /** -------------------------创建数据源------------------------- **/ 35 /** 36 * 通过实例化的方式来获取数据源 37 * 38 * @return 39 * @throws PropertyVetoException 40 * @throws SQLException 41 */ 42 public static ComboPooledDataSource createByInitInstance() 43 throws PropertyVetoException, SQLException { 44 // 创建实例 45 ComboPooledDataSource dataSource = new ComboPooledDataSource(""); 46 // 连接时配置 47 // dataSource = connDatabaseConfig(dataSource, "masterOracle"); 48 return dataSource; 49 } 50 51 /** 52 * 创建多个数据源,每个数据源通过名字区分 53 * 54 * @return 55 * @throws IOException 56 * @throws SQLException 57 * @throws PropertyVetoException 58 */ 59 public static ComboPooledDataSource createMultiDataSource() 60 throws IOException, SQLException, PropertyVetoException { 61 // 创建数据库实例masterOracle 62 ComboPooledDataSource masterOracleDataSource = new ComboPooledDataSource("masterOracle"); 63 // 连接时配置masterOracle数据源 64 masterOracleDataSource = connDatabaseConfig(masterOracleDataSource, "masterOracle"); 65 // 创建数据库实例orcl 66 ComboPooledDataSource orclDataSource = new ComboPooledDataSource("orcl"); 67 // 连接时配置orcl数据源 68 orclDataSource = connDatabaseConfig(orclDataSource, "orcl"); 69 // 执行测试语句 70 runSQLTest(masterOracleDataSource); 71 // 执行测试语句 72 runSQLTest(orclDataSource); 73 return masterOracleDataSource; 74 } 75 76 /** 77 * 通过DataSources工厂方式建立连接 78 * 79 * @return 80 * @throws SQLException 81 */ 82 public static DataSource createByFactory() throws SQLException { 83 // 创建unpooled的数据源 84 DataSource ds_unpooled = 85 DataSources.unpooledDataSource(masterOraclejdbcUrl, user, password); 86 // pooled数据源的参数 87 Map<String, String> paramMap = new HashMap<>(); 88 ComboPooledDataSource pooled = 89 (ComboPooledDataSource) DataSources.pooledDataSource(ds_unpooled, paramMap); 90 runSQLTest(pooled); 91 pooled.close(); 92 DataSources.destroy(pooled); 93 return pooled; 94 } 95 96 /** -----------------------配置数据源----------------------------- **/ 97 /** 98 * 配置数据源 99 * 100 * @param dataSource 101 * @return 102 * @throws PropertyVetoException 103 */ 104 public static ComboPooledDataSource configDataSource(ComboPooledDataSource dataSource) 105 throws PropertyVetoException { 106 // 连接数据库的必要属性 107 connDatabaseConfig(dataSource,"masterOracle"); 108 // 连接池的相关配置 109 connPoolConfig(dataSource); 110 // 连接对象的生命周期配置 111 connAgeConfig(dataSource); 112 // 测试连接的配置 113 connTestConfig(dataSource); 114 // statement对象的配置 115 statementConfig(dataSource); 116 // 重连配置 117 reconnConfig(dataSource); 118 // 连接的监听类配置 119 connListenerConfig(dataSource); 120 // 事务的配置 121 tranConfig(dataSource); 122 // 调试模式 123 debugMode(dataSource); 124 // 线程配置 125 threadConfig(dataSource); 126 return dataSource; 127 } 128 129 130 131 /** 132 * 连接池的配置 initialPoolSize:连接池的初始值 maxPoolSize:连接池的最大值 minPoolSize:连接池的最小值 133 * 134 * @param dataSource 135 */ 136 private static void connPoolConfig(ComboPooledDataSource dataSource) { 137 // 连接池的初始值,默认值为3 138 dataSource.setInitialPoolSize(10); 139 // 连接池的最大值,默认值为0 140 dataSource.setMaxPoolSize(20); 141 // 连接池的最小值,最小值为3 142 dataSource.setMinPoolSize(1); 143 // 连接池的递增值,默认值为3 144 dataSource.setAcquireIncrement(5); 145 } 146 147 /** 148 * 连接池生命周期配置,连接池首先从数据库中获取连接,用户请求时从连接池中获取连接。默认值为0,表示永不过期。 maxConnectionAge: 149 * 连接对象生命的最大值,超过此时间,连接池会销毁连接对象,连接池变小。单位为秒,建议设置1800或更多 maxIdleTime: 150 * 空闲连接在连接池中的超时时间,超过此时间,连接池将会销毁连接对象。单位为秒,建议设置1800或更多 151 * maxIdleTimeExcessConnections:当连接池不处于过载状态时,空闲连接对象生命的最大值。 152 * unreturnedConnectionTimeout:当连接对象在一定时间内无法回收,则创建新连接对象,销毁旧连接对象 153 * 154 * @param dataSource 155 */ 156 private static void connAgeConfig(ComboPooledDataSource dataSource) { 157 // 连接对象生命的最大值,它指绝对时间。从创建开始时计算,默认值为0 158 dataSource.setMaxConnectionAge(10 * 60 * 60); 159 // 空闲连接的超时时间,从连接池变为空闲状态开始计算 160 dataSource.setMaxIdleTime(1800); 161 // 空闲连接对象生命的最大值 162 dataSource.setMaxIdleTimeExcessConnections(60); 163 // 连接对象的最大使用时间,设置为2小时 164 dataSource.setUnreturnedConnectionTimeout(2 * 60 * 60); 165 } 166 167 168 /** 169 * 连接测试配置。 automaticTestTable:测试连接时使用的数据库表 ,默认值为null。connectionTesterClassName:测试连接时使用的类名称 170 * idleConnectionTestPeriod:测试连接间隔时间。在此段时间内不进行连接测试。 preferredTestQuery:连接测试使用的SQL语句。默认语句为select 171 * 1 from dual。 testConnectionOnCheckin:从连接池回收连接对象时测试连接。默认值为false 172 * testConnectionOnCheckOut:从连接池取出连接对象时测试连接。默认值为false。 173 * forceSynchronousCheckins:连接池回收连接对象时是同步,还是异步,默认是异步。默认值为false 174 * 175 * @param dataSource 176 * @throws PropertyVetoException 177 */ 178 private static void connTestConfig(ComboPooledDataSource dataSource) 179 throws PropertyVetoException { 180 // 连接测试使用的数据库表,默认值为Null 181 dataSource.setAutomaticTestTable("dual"); 182 // 连接测试使用的SQL语句,默认使用Connection对象的isAlive方法,所以一般不设置此值,默认值为null 183 dataSource.setPreferredTestQuery("select 1"); 184 // 从连接池取出连接时测试连接,默认值为false 185 dataSource.setTestConnectionOnCheckout(true); 186 // 从连接池回收连接时测试连接,默认值为false。 187 dataSource.setTestConnectionOnCheckin(true); 188 // 测试连接的间隔时间,默认值为0 189 dataSource.setIdleConnectionTestPeriod(60); 190 // 测试连接使用的类名称 191 dataSource.setConnectionTesterClassName("com.rain.Tester.ConnectionTesterSample"); 192 } 193 194 /** 195 * 连接池中PreparedStatement对象的配置 PreparedStatement对象的配置。 maxStatements:连接池拥有PreparedStatement对象的总数。 196 * maxStatementsPerConnections:每个连接拥有PreparedStatement对象的数目。 197 * 198 * @param dataSource 199 */ 200 private static void statementConfig(ComboPooledDataSource dataSource) { 201 // 设置PreparedStatement对象的总数,默认值为0,表示关闭 202 dataSource.setMaxStatements(100); 203 // 设置每个连接拥有Statement对象的数目,默认值为0,表示关闭。 204 dataSource.setMaxStatementsPerConnection(15); 205 } 206 207 /** 208 * 当连接失败后,重新连接的配置。 acquireRetryAttempts:重连的次数。 acquireRetryDelay:重连的时间间隔。单位为毫秒 209 * breakAfterAcquireFailure:重连失败后,如果此值设置为false,数据源对象不会销毁,设置为false。数据源被销毁。 210 * checkoutTimeout:等待连接响应的时间。 211 */ 212 private static void reconnConfig(ComboPooledDataSource dataSource) { 213 // 设置重连次数为3,默认值为30 214 dataSource.setAcquireRetryAttempts(3); 215 // 设置重连的时间间隔为2秒,默认值为1000 216 dataSource.setAcquireRetryDelay(2000); 217 // 等待连接响应的超时时间。默认值为0表示永远不超时 218 dataSource.setCheckoutTimeout(4); 219 // 重连失败后,销毁数据源。默认值为false 220 dataSource.setBreakAfterAcquireFailure(true); 221 } 222 223 /** 224 * 设置连接对象的监听类,该类有四个方法 onAcquire:表示当连接池从数据库中获得连接时 onDestory:表示当连接池销毁连接对象时 onCheckOut:从连接池中获取连接对象时 225 * onCheckIn:连接池回收连接对象时。 226 */ 227 private static void connListenerConfig(ComboPooledDataSource dataSource) { 228 // 设置连接对象的监听类 229 dataSource.setConnectionCustomizerClassName("com.rain.Tester.ConnCustomrizerSample"); 230 } 231 232 /** 233 * 连接对象的事务配置 autoCommitOnClose:是否自动提交事务,true为是,false为否,默认为否 forceIgnoreUnresolvedTransactions 234 * 回收连接时,是否强制回滚或提交事务,默认为false。一般不设置此值, 例如由Spring来管理事务 235 * 236 * @param dataSource 237 */ 238 private static void tranConfig(ComboPooledDataSource dataSource) { 239 // 关闭自动提交事务,默认值为false 240 dataSource.setAutoCommitOnClose(false); 241 // 回收连接时,是否强制回滚或提交事务,设置为false。 242 dataSource.setForceIgnoreUnresolvedTransactions(false); 243 244 } 245 246 /** 247 * 调试模式的设置 debugUnreturnedConnectionStackTraces:从连接池获取连接对象时,打印所有信息 248 249 * 250 * @param dataSource 251 */ 252 private static void debugMode(ComboPooledDataSource dataSource) { 253 // 从连接池获取连接对象时,打印所有信息 254 dataSource.setDebugUnreturnedConnectionStackTraces(true); 255 } 256 257 /** 258 * 类加载器的设置。 contextClassLoaderSource:可选值为caller,none,library。默认值为caller,一般不设置此值。 259 * privilegeSpawnedThreads: 260 * 261 * @param dataSource 262 */ 263 private static void classLoaderConfig(ComboPooledDataSource dataSource) { 264 // dataSource.getContext 265 } 266 267 /** 268 * 连接池的线程设置 numHelperThread:连接池拥有的线程数量 maxAdministrativeTaskTime:线程执行的超时时间。 269 * 270 * @param dataSource 271 */ 272 private static void threadConfig(ComboPooledDataSource dataSource) { 273 // 设置线程数量为10,默认值为3 274 dataSource.setNumHelperThreads(10); 275 // 设置线程的超时时间,默认值为0,设置为5分钟 276 dataSource.setMaxAdministrativeTaskTime(5 * 60); 277 } 278 279 /** 280 * 连接池的日志配置,mchange-log.properties提供默认配置 281 * 282 * @param dataSource 283 */ 284 private static void logConfig(ComboPooledDataSource dataSource) { 285 // 设置com.mchange.v2.log.MLog 286 // 设置com.mchange.v2.log.jdk14logging.suppressStackWalk 287 // 设置com.mchange.v2.log.NameTransformer 288 // 设置com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL,可选值为 289 // OFF,SERVER,WARNING,INFO,FINE,FINER,FINEST,ALL 290 } 291 292 /** 293 * 其他配置项 294 * 295 * @param dataSource 296 */ 297 private static void otherConfig(ComboPooledDataSource dataSource) { 298 // 设置factoryClassLocation 299 // 设置forceSynchronousCheckins 300 // statementCacheNumDeferredCloseThreads 301 // com.mchange.v2.c3p0.cfg.xml 302 // com.mchange.v2.c3p0.impl.DefaultConnectionTester.querylessTestRunner 303 // com.mchange.v2.c3p0.impl.DefaultConnectionTester.isValidTimeout 304 } 305 306 /** 307 * 打印连接池的属性 308 * 309 * @param dataSource 310 */ 311 private static void printDataSourceInfo(ComboPooledDataSource dataSource) { 312 // 连接时的必要属性 313 System.out.println("——————————————————————————————————————————————————————————————————————"); 314 System.out.println("||-------------------连接数据库的必要属性-----------------||"); 315 System.out.println("数据源的驱动类名称:" + dataSource.getDriverClass()); 316 System.out.println("数据源的连接URL:" + dataSource.getJdbcUrl()); 317 System.out.println("数据源的连接用户名:" + dataSource.getUser()); 318 System.out.println("数据源的连接密码:" + dataSource.getPassword()); 319 System.out.println("数据源的Id:" + dataSource.getIdentityToken()); 320 // 连接池的基本配置 321 System.out.println("——————————————————————————————————————————————————————————————————————"); 322 System.out.println("||-------------------连接池大小配置---------------------||"); 323 System.out.println("连接池的初始需求量大小:" + dataSource.getInitialPoolSize()); 324 System.out.println("连接池的最大值:" + dataSource.getMaxPoolSize()); 325 System.out.println("连接池的最小值:" + dataSource.getMinPoolSize()); 326 System.out.println("当无可用连接时,连接池需求量的递增值:" + dataSource.getAcquireIncrement()); 327 // 连接对象的生命周期配置 328 System.out.println("——————————————————————————————————————————————————————————————————————"); 329 System.out.println("||-------------------连接对象的生命周期--------------------||"); 330 System.out.println("连接对象的最大生存时间,从创建连接对象时开始计时:" + dataSource.getMaxConnectionAge()); 331 System.out.println("空闲连接对象的超时时间,从连接对象变为空闲状态开始计时:" + dataSource.getMaxIdleTime()); 332 System.out.println("当连接池负载较低时,空闲连接对象的最大生命年龄:" + dataSource.getMaxIdleTimeExcessConnections()); 333 System.out.println("从连接池获取连接对象之后,连接对象的超时时间:"+dataSource.getUnreturnedConnectionTimeout()); 334 // 测试连接的配置 335 System.out.println("——————————————————————————————————————————————————————————————————————"); 336 System.out.println("||-------------------测试连接的配置----------------------||"); 337 System.out.println("测试连接使用的数据库表:" + dataSource.getAutomaticTestTable()); 338 System.out.println("测试连接使用的SQL语句:" + dataSource.getPreferredTestQuery()); 339 System.out.println("从连接池中获取连接时是否进行连接测试:" 340 + convertBooleanToStr(dataSource.isTestConnectionOnCheckout())); 341 System.out.println("从连接池中回收连接时是否进行连接测试:" 342 + convertBooleanToStr(dataSource.isTestConnectionOnCheckin())); 343 System.out.println("测试连接的时间间隔:" + dataSource.getIdleConnectionTestPeriod() + "秒"); 344 System.out.println("测试连接使用的类名称:" + dataSource.getConnectionTesterClassName()); 345 // 重连配置 346 System.out.println("——————————————————————————————————————————————————————————————————————"); 347 System.out.println("||-------------------重连配置-----------------||"); 348 System.out.println("连接失败后,尝试重连的次数:" + dataSource.getAcquireRetryAttempts()); 349 System.out.println("重连的时间间隔:" + dataSource.getAcquireRetryDelay()+"毫秒"); 350 System.out.println("用户等待连接的超时时间:" + dataSource.getCheckoutTimeout()); 351 System.out.println( 352 "重连失败后,是否销毁数据源:" + convertBooleanToStr(dataSource.isBreakAfterAcquireFailure())); 353 // 缓存preparedStatement对象的配置 354 System.out.println("——————————————————————————————————————————————————————————————————————"); 355 System.out.println("||-------------------缓存preparedStatement对象的配置-----------------||"); 356 System.out.println("连接池拥有PreparedStatement对象的总数:" + dataSource.getMaxStatements()); 357 System.out.println( 358 "每个连接拥有PreparedStatement对象的数量:" + dataSource.getMaxStatementsPerConnection()); 359 // 线程设置 360 System.out.println("——————————————————————————————————————————————————————————————————————"); 361 System.out.println("||-------------------线程设置--------------------------||"); 362 System.out.println("连接池拥有的线程数量:" + dataSource.getNumHelperThreads()); 363 System.out.println( 364 "线程执行的超时时间:" + dataSource.getMaxAdministrativeTaskTime()); 365 // 设置事务 366 System.out.println("——————————————————————————————————————————————————————————————————————"); 367 System.out.println("||-------------------事务配置---------------------------||"); 368 System.out 369 .println("连接对象的事务是否自动提交:" + convertBooleanToStr(dataSource.isAutoCommitOnClose())); 370 System.out.println("回收连接对象时,是否强制提交和回滚事务:" 371 + convertBooleanToStr(dataSource.isForceIgnoreUnresolvedTransactions())); 372 // 设置调试模式 373 System.out.println("——————————————————————————————————————————————————————————————————————"); 374 System.out.println("||-------------------调试模式配置-----------------------||"); 375 System.out.println("从连接池获取连接对象时,是否打印所有信息:" 376 + convertBooleanToStr(dataSource.isDebugUnreturnedConnectionStackTraces())); 377 // 监听类 378 System.out.println("——————————————————————————————————————————————————————————————————————"); 379 System.out.println("||-------------------监听类名称-----------------||"); 380 System.out.println("连接对象的监听类名称:" + dataSource.getConnectionCustomizerClassName()); 381 382 383 384 385 } 386 387 /** 388 * 运行测试用例,执行select 1 from dual 语句。 389 * 390 * @param dataSource 391 * @throws SQLException 392 */ 393 private static void runSQLTest(ComboPooledDataSource dataSource) throws SQLException { 394 // 建立连接 395 Connection conn = dataSource.getConnection(); 396 // 创建Statement对象 397 Statement statement = conn.createStatement(); 398 // 处理结果集 399 ResultSet rs = statement.executeQuery("select 1 from dual"); 400 printResultSet(rs); 401 } 402 403 private static void printResultSet(ResultSet rs) throws SQLException { 404 while (rs.next()) { 405 System.out.println("返回结果集为:" + rs.getInt(1)); 406 } 407 } 408 409 /** 410 * 连接数据库时的必要配置, driverClass:驱动类 jdbcUrl:数据库实例url,格式为jdbc:subprotocol:subname 411 * user:用户名,其他数据源有时候使用username表示,拥有相同的含义。 password:密码,用户密码 412 * 413 * @param dataSource 414 * @return 415 * @throws PropertyVetoException 416 */ 417 public static ComboPooledDataSource connDatabaseConfig(ComboPooledDataSource dataSource, 418 String dsName) throws PropertyVetoException { 419 String jdbcUrl = null; 420 switch (dsName) { 421 case "masterOracle": 422 jdbcUrl = masterOraclejdbcUrl; 423 break; 424 case "orcl": 425 jdbcUrl = orclJdbcUrl; 426 break; 427 default: 428 break; 429 } 430 // 设置数据库url 431 dataSource.setJdbcUrl(jdbcUrl); 432 // 设置数据库驱动类 433 dataSource.setDriverClass(driverClassName); 434 // 设置用户名 435 dataSource.setUser(user); 436 // 设置密码 437 dataSource.setPassword(password); 438 // 输出dataSourceName,在初始化ComboPooledDataSource时,字符串参数作为数据源名称, 439 dataSource.getDataSourceName(); 440 return dataSource; 441 } 442 443 /** 444 * 将布尔值true转换为是,布尔值false转换为否 445 * 446 * @param value 447 * @return 448 */ 449 private static String convertBooleanToStr(boolean value) { 450 if (value) { 451 return "是"; 452 } else { 453 return "否"; 454 } 455 } 456 }
Properties方式:在类加载路径下,配置项有c3p0前缀
##-------------------------------数据库连接属性-----------------------------------## # 驱动类名称 c3p0.driverClass=oracle.jdbc.driver.OracleDriver # 数据库实例url地址 c3p0.jdbcUrl=jdbc:oracle:thin:@localhost:1521:masteroracle # 用户名 c3p0.user=system # 密码 c3p0.password=password ##-------------------------------调试模式--------------------------------------## # 当从连接池获取连接对象时,打印所有信息。 c3p0.debugUnreturnedConnectionStackTraces=true ##-------------------------------日志配置--------------------------------------## # 日志的实现方式 #com.mchange.v2.log.MLog=log4j # 日志的级别,OFF,SERVER,WARNING,INFO,FINE,FINER,FINEST,ALL com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL=All # 日志按包输出 com.mchange.v2.log.NameTransformer=com.mchange.v2.log.PackageNames # determine the class and method from which a log message was generated,当为true时,不打印这些日志信息 com.mchange.v2.log.jdk14logging.suppressStackWalk=true ##-------------------------------连接池配置-------------------------------------## # 连接池拥有连接对象的初始值,这种情形下只是Acquire(需求)的初始值,真正创建对象会根据Acquire来按需创建 c3p0.initialPoolSize=10 # 连接池拥有连接对象的最大值,默认值为3 c3p0.maxPoolSize=20 # 连接池拥有连接对象的最小值,默认值为3 c3p0.minPoolSize=5 # 当无空闲连接时,新创建的连接数,默认值为3 c3p0.acquireIncrement=3 ##-------------------------------连接生命周期--------------------------## # 连接对象的最大生存时间,起始时间从连接池从数据库中创建连接对象开始计算。0表示永远不销毁 c3p0.maxConnectionAge=0 # 空闲连接对象的超时时间,起始时间从连接对象状态变为空闲时起计算。 c3p0.maxIdleTime=1800 # 当连接池不处于满载状态时,空闲连接对象的最大生存时间,设置此值,可以快速的减少连接池的大小 c3p0.maxIdleTimeExcessConnections=60 # 连接对象回收的超时时间,当连接池无法在一定时间内回收连接对象时,销毁旧对象,重新创建新对象 c3p0.unreturnedConnectionTimeout=600 ##-------------------------------测试连接配置项----------------------------------## # 从连接池中获取连接对象时进行连接测试 c3p0.testConnectionOnCheckout=true # 从连接池回收对象时进行连接测试 c3p0.testConnectionOnCheckin=true # 连接测试的间隔,在这一段时间内不进行连接测试 c3p0.idleConnectionTestPeriod=60 # 连接测试时使用的类,设置此值时忽略preferredTestQuery,automaticTestTable等属性值 #c3p0.connectionTesterClassName=com.rain.Tester.ConnectionTesterSample # 测试的SQL语句 c3p0.preferredTestQuery=select 1 # 连接测试时使用的数据库表 c3p0.automaticTestTable=test ##-------------------------------重新连接---------------------------------------## # 重新连接的次数 c3p0.acquireRetryAttempts=5 # 重新连接的时间间隔,单位为毫秒 c3p0.acquireRetryDelay=3000 # 等待连接响应的超时时间 c3p0.checkoutTimeout=120 # 当连接失败时,是否销毁数据源对象,true表示是,false表示否 c3p0.breakAfterAcquireFailure=true ##-------------------------------statement对象相关配置---------------------------## # c3p0拥有的PreparedStatement对象的总数 c3p0.maxStatements=100 # 每个连接拥有PreparedStament对象的数量 c3p0.maxStatementsPerConnection=10 # 当Connection对象关闭时,启动额外线程确保statement对象关闭 # This parameter should only be set if you observe that attempts by c3p0 to close() cached statements freeze statementCacheNumDeferredCloseThreads=1 ##-------------------------------线程池----------------------------------------## # 连接池拥有的线程数量 c3p0.numHelperThreads=5 # 线程执行的最大时间 c3p0.maxAdministrativeTaskTime=600 # 启动独立的线程来在连接被连接池回收阶段进行测试 forceSynchronousCheckins=true ##-------------------------------事务-----------------------------------------## # 交给Spring去管理事务,默认不配置这些项 # 连接关闭时,是否自动提交事务 c3p0.autoCommitOnClose=false # 连接回收时,是否强制提交或者回滚当前连接拥有的事务,默认不配置。 c3p0.forceIgnoreUnresolvedTransactions=false ##-------------------------------监听类---------------------------------------## c3p0.connectionCustomizerClassName=com.rain.Tester.ConnCustomrizerSample ##-------------------------------类加载器配置------------------------------------## # contextClassLoaderSource should be set to one of caller, library, or none c3p0.contextClassLoaderSource=caller # privilegeSpawnedThreads is a boolean, false by default. Set this to true so that c3p0‘s Threads use the # c3p0 library‘s AccessControlContext, rather than an AccessControlContext that may be associated with # the client application and prevent its garbage collection. privilegeSpawnedThreads=false
xml方式:com.mchange.v2.c3p0.cfg.xml指定c3p0-config.xml的路径
System属性:System.setProperty(key,value)。
验证
代码方式的执行结果
—————————————————————————————————————————————————————————————————————— ||-------------------连接数据库的必要属性-----------------|| 数据源的驱动类名称:oracle.jdbc.driver.OracleDriver 数据源的连接URL:jdbc:oracle:thin:@localhost:1521:masteroracle 数据源的连接用户名:system 数据源的连接密码:password 数据源的Id:1hge1639oxiibou10417lr|7506e922 —————————————————————————————————————————————————————————————————————— ||-------------------连接池大小配置---------------------|| 连接池的初始需求量大小:10 连接池的最大值:20 连接池的最小值:5 当无可用连接时,连接池需求量的递增值:3 —————————————————————————————————————————————————————————————————————— ||-------------------连接对象的生命周期--------------------|| 连接对象的最大生存时间,从创建连接对象时开始计时:0 空闲连接对象的超时时间,从连接对象变为空闲状态开始计时:1800 当连接池负载较低时,空闲连接对象的最大生命年龄:60 从连接池获取连接对象之后,连接对象的超时时间:600 —————————————————————————————————————————————————————————————————————— ||-------------------测试连接的配置----------------------|| 测试连接使用的数据库表:test 测试连接使用的SQL语句:select 1 从连接池中获取连接时是否进行连接测试:是 从连接池中回收连接时是否进行连接测试:是 测试连接的时间间隔:60秒 测试连接使用的类名称:com.mchange.v2.c3p0.impl.DefaultConnectionTester —————————————————————————————————————————————————————————————————————— ||-------------------重连配置-----------------|| 连接失败后,尝试重连的次数:5 重连的时间间隔:3000毫秒 用户等待连接的超时时间:120 重连失败后,是否销毁数据源:是 —————————————————————————————————————————————————————————————————————— ||-------------------缓存preparedStatement对象的配置-----------------|| 连接池拥有PreparedStatement对象的总数:100 每个连接拥有PreparedStatement对象的数量:10 —————————————————————————————————————————————————————————————————————— ||-------------------线程设置--------------------------|| 连接池拥有的线程数量:5 线程执行的超时时间:600 —————————————————————————————————————————————————————————————————————— ||-------------------事务配置---------------------------|| 连接对象的事务是否自动提交:否 回收连接对象时,是否强制提交和回滚事务:否 —————————————————————————————————————————————————————————————————————— ||-------------------调试模式配置-----------------------|| 从连接池获取连接对象时,是否打印所有信息:是 —————————————————————————————————————————————————————————————————————— ||-------------------监听类名称-----------------|| 连接对象的监听类名称:com.rain.Tester.ConnCustomrizerSample
参考资料
C3p0 —— JDBC 3 Connection and Statement Pooling http://www.mchange.com/projects/c3p0
功能第二篇——数据源之C3P0数据源(JDBC)