c3p0是一个成熟的、高并发的JDBC链接池,它随Hibernate一同分发,但愿提供一个优秀的J2EE企业级应用的数据源实现。html
c3p0:java
java.sql.DataSource
视图都兼容的获取数据库链接的类。PreparedStatement
,使传统的驱动和任意的未入池的数据源都能得到环绕式的处理。
c3p0-0.9.5-pre8
须要1.6.x
或者更高版本的Java运行环境。mysql
将lib/c3p0-0.9.5-pre8.jar
和lib/mchange-commons-java-0.27.jar
两个文件放入你的CLASSPASS
下(或者你的类加载器可以加载的任何地方)。程序员
建立数据源:web
1 2 3 4 5 6 7 |
import com.mchange.v2.c3p0.*; ... ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" ); cpds.setUser("dbuser"); cpds.setPassword("dbpassword"); |
[可选]:若是你须要开启PreparedStatement池,你必须设置maxStatements和/或maxStatementsPerConnection两个值(默认都为0)。sql
1 |
cpds.setMaxStatements(180); |
数据源底层的链接池将使用默认参数建立,你能够对数据源进行任何操做。你能够根据你的喜爱将数据源绑定到JNDI命名空间或者直接使用它。数据库
当你使用完毕的时候,你能够销毁数据源:apache
1 |
cpds.close(); |
c3p0提供标准的JDBC2数据源对象。用户能够在建立数据源对象时控制与池有关的、与命名有关的属性等。全部的池管理操做在数据源对象被建立后都是对用户彻底透明的。编程
建立c3p0数据源有三种方式:后端
ComboPooledDataSource bean
。PoolBackedDataSource
并设定它的ConectionPoolDataSource
。若是不指定配置的话,c3p0将使用默认参数建立数据源。
一旦实例化成功,c3p0数据源就能够和与JNDI标准兼容的命名服务绑定。
c3p0内置了硬编码的配置,但你能够经过建立一个c3p0.properties
文件并将其放置在加载c3p0的jar文件的CLASSPATH
(或类加载器)的顶级目录下以覆盖配置信息。
更多的配置信息请看下一章。
实例化一个com.mchange.v2.c3p0.ComboPooledDataSource
是建立c3p0池数据源的最直接方式。这是一个JavaBean
风格的,拥有一个无参数的Public
构造方法的类。确保你在使用它以前设定了jdbcUrl
属性。你也能够根据须要设定user
和password
属性。若是你使用了未预加载的老式JDBC驱动,你还应当设定driverClass
属性。
1 2 3 4 5 6 7 8 9 10 |
ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" ); cpds.setUser("swaldman"); cpds.setPassword("test-password"); // the settings below are optional -- c3p0 can work with defaults cpds.setMinPoolSize(5); cpds.setAcquireIncrement(5); cpds.setMaxPoolSize(20); // The DataSource cpds is now a fully configured and usable pooled DataSource ... |
任何一个c3p0 DataSource
的实例的初状态都取决于你提供的配置或者还原为硬编码的默认配置。
c3p0支持命名配置以配置多个数据源。
你能够构造本身的com.mchange.v2.c3p0.ComboPooledDataSource
命名配置:
1 |
ComboPooledDataSource cpds = new ComboPooledDataSource("intergalactoApp"); |
固然,你仍然能够经过前面所述的编程方式来覆盖配置信息。
此外,你还可使用静态工厂类Com.mchange.v2.c3p0.DataSources
来从传统的JDBC驱动里建立未入池的数据源,并用它来构造一个池化的数据源:
1 2 3 4 5 6 7 8 |
DataSource ds_unpooled = DataSources.unpooledDataSource( "jdbc:postgresql://localhost/testdb", "swaldman", "test-password"); DataSource ds_pooled = DataSources.pooledDataSource( ds_unpooled ); // The DataSource ds_pooled is now a fully configured and usable pooled DataSource. // The DataSource is using a default pool configuration, and Postgres' JDBC driver // is presumed to have already been loaded via the jdbc.drivers system property or an // explicit call to Class.forName("org.postgresql.Driver") elsewhere. ... |
若是你使用了这个数据源工厂类,而且想要编程式覆盖默认配置,你能够经过提供一个map
来实现:
1 2 3 4 5 6 7 8 9 10 11 12 |
DataSource ds_unpooled = DataSources.unpooledDataSource( "jdbc:postgresql://localhost/testdb", "swaldman", "test-password"); Map overrides = new HashMap(); overrides.put("maxStatements", "200");//Stringified property values work overrides.put("maxPoolSize", new Integer(50)); //"boxed primitives" also work // create the PooledDataSource using the default configuration and our overrides ds_pooled = DataSources.pooledDataSource( ds_unpooled, overrides ); // The DataSource ds_pooled is now a fully configured and usable pooled DataSource, // with Statement caching enabled for a maximum of up to 200 statements and a maximum // of 50 Connections. ... |
若是你使用命名配置,你能够指定一个命名来配置你的数据源:
1 2 |
// create the PooledDataSource using the a named configuration and specified overrides ds_pooled = DataSources.pooledDataSource(ds_unpooled, "intergalactoAppConfig", overrides ); |
c3p0数据源依赖着一个包括ComboPooledDataSource
的实现和DataSources.pooledDataSource(...)
方法返回对象,以及实现com.mchange.v2.c3p0.PooledDataSource
全部接口的池。这使得有大量查询数据源链接池状态的方法可用。
查询数据源状态的实例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// fetch a JNDI-bound DataSource InitialContext ictx = new InitialContext(); DataSource ds = (DataSource) ictx.lookup( "java:comp/env/jdbc/myDataSource" ); // make sure it's a c3p0 PooledDataSource if (ds instanceof PooledDataSource){ PooledDataSource pds = (PooledDataSource) ds; System.err.println("num_connections:"+ pds.getNumConnectionsDefaultUser()); System.err.println("num_busy_connections:"+pds.getNumBusyConnections DefaultUser()); System.err.println("num_idle_connections:"+pds.getNumIdleConnections DefaultUser()); System.err.println(); } else System.err.println("Not a c3p0 PooledDataSource!"); |
这些状态查询方法有三种重载方式:
public int getNumConnectionsDefaultUser()
public int getNumConnections(String username, String password)
public int getNumConnectionsAllUsers()
最简单的清理c3p0 PooledDataSources
的方法就是调用DataSources
类的destory
方法。只有PooledDataSource
对象须要被清理。对非池化或非c3p0数据源调用DataSources.destory(...)
方法也无妨。
1 2 3 4 5 6 7 8 9 10 11 |
DataSource ds_pooled = null; try{ DataSource ds_unpooled = DataSources.unpooledDataSource( "jdbc:postgresql://localhost/testdb","swaldman","test-password"); ds_pooled = DataSources.pooledDataSource( ds_unpooled ); // do all kinds of stuff with that sweet pooled DataSource... } finally{ DataSources.destroy( ds_pooled ); } |
此外,你能够经过调用c3p0的PooledDataSource
接口的close()
方法来关闭DataSource
对象。所以,你能够将DataSource
对象转换成PooledDataSource
对象而后关闭它。
1 2 3 4 5 6 7 8 9 |
static void cleanup(DataSource ds) throws SQLException{ // make sure it's a c3p0 PooledDataSource if ( ds instanceof PooledDataSource){ PooledDataSource pds = (PooledDataSource) ds; pds.close(); } else System.err.println("Not a c3p0 PooledDataSource!"); } |
ComboPooledDatasource
是PooledDataSource
的一个实例,也能直接被它的close()
方法关闭。
在用户调用close()
方法而被关闭以前,未被引用的PooledDataSource
实例不会被垃圾回收器调用finalize()
而被关闭。自动销毁机制和一般同样,只是一种辅助方法,而不用来确保资源的清理。
你能够经过这种方法来一步步地建立一个PoolBackedDataSource
(对大多数程序员来讲并没必要要):
若是你的驱动提供了
ConnectionPoolDataSource
的实现,你只须要:
实例化并配置一个非池化的DriverManagerDataSource
,以后实例化一个WrapperConnectionPoolDataSource
,将非池化的数据源设置为它的nestedDataSource
属性,而后将它设定为一个PoolBackedDataSource
对象的connectionPoolDataSource
属性。
除了使用c3p0的WrapperConeectionPoolDataSource
以外,你还能够建立一个PollBackedDataSource
,然 后 设 定 它 的connectionPoolDataSource
属 性。第三方的ConnectionPoolDataSource
不支持Statement池
,ConnectionCustomizers
,和一些特定的 c3p0属性(第三方的 DataSource 实现能够用来替代c3p0的DriverManagerDataSource
,这在功能上并无什么明显的损失)。
JDBC驱动在实现Connection
和Statement
上有时定义了一些与特定厂商的,不标准的API。c3p0将这些对象包装进了一个代理里,因此你不能把c3p0返回的 Connection
或Statement
转换成特定厂商的实现。c3p0没有提供任何可以直接访问原生链接和Statement
的方法,这是由于c3p0须要一直按顺序地追踪Statement和结果集的建立,来防止资源紧缺和池讹误(pool corruption
)现象。
c3p0提供了一个能让你经过反射在底层的链接上来执行非标准方法的API。使用方法是:
首先将返回的Connection
转 换 成 一 个C3P0ProxyConnection
。而后调用rawConnectionOperation
方法,而后提供一个你想要执行的 java.lang.reflect.Method
对象做为这个非标准方法的参数。你提供的这个Method对象将会在第二个参数(null
或者静态方法)上执行,而且使用你提供的第三个参数来完成这个方法。对目标对象和这个方法的全部参数来说,你均可以使用 C3P0ProxyConnection.RAW_CONNECTION
这个特殊的标记,它将会在方法执行前替代底层的特定厂商的Connection
。
C3P0ProxyStatement
也提供了相似的API。
原生操做返回的全部Statement
(包括Prepared
和CallableStatement
)和ResultSet
都是被c3p0所管理的,因此在其父代理链接上调用close()
方法的时候它们都会被正确地清理。用户必须注意清理那些与特定厂商相关的方法返回的那些非标准的资源。
使用 Oracle特定的API在原生链接上调用静态方法的例子:
1 2 3 4 |
C3P0ProxyConnection castCon = (C3P0ProxyConnection) c3p0DataSource.getConnection(); Method m = CLOB.class.getMethod("createTemporary", new Class[]{Connection.class, boolean.class, int.class}); Object[] args = new Object[] {C3P0ProxyConnection.RAW_CONNECTION, Boolean.valueOf( true ), new Integer( 10 )}; CLOB oracleCLOB = (CLOB) castCon.rawConnectionOperation(m, null, args); |
C3P0 如今支持一些 Oracle 特定的方法了,在本文的其余相关中有详细的介绍。
c3p0没有过多的必须(required)配置信息,它很是灵活可控。大多数的配置信息都是JavaBean
属性。下面就是 JavaBean
的惯例,若是有一个对象有一个类型为 T
的属性 foo
,这个对象就会有相似这样的方法…
public T getFoo();
public void setFoo(T foo);
这样的方法是否成对存在,取决于这个属性是只可读的,只可写,仍是可读写的。
有多种方法修改 c3p0 的属性:你能够直接在代码里经过关联一个特定的数据源来改变配置,你也能够在外部经过简单的Java属性文件(simple Java properties file),XML配置文件或系统属性来配置c3p0。一般来说,配置文件都被命名为c3p0.properties
或c3p0-config.xml
,并放置在应用的CLASSPATH
的顶级路径中,可是 XML 配置文件能够被放在应用所在的文件系统的任何位置,你只须要改变 com.mchange.v2.c3p0.cfg.xml
这个系统属性便可(绝对路径)。
数据源一般在使用以前被配置,好比在构造方法中配置或者在构造方法返回以后立刻进
行配置。不过 c3p0 也支持使用过程当中修改配置。
若是你经过调用工具类com.mchange.v2.c3p0.DataSources
的工厂方法来获取数据源,而且不但愿这个数据源使用默认的配置,那么你能够提供一个Map
类型的参数做为配置信息[key必须是小写字母开头的属性名,value能够是字符串或者“被打包(boxed)”的Java原生类型,例如Integer
和Boolean
]。
全部可改变的属性在附录中都有详细的文档。
c3p0 链接池能够经过下面几个基本参数来简单地配置:
acquireIncrement
initialPoolSize
maxPoolSize
maxIdleTime
minPoolSize
initialPoolSize
, minPoolSize
, maxPoolSize
定义了由池管理的链接数量。请确保minPoolSize
<=maxPoolSize
。不合理的initialPoolSize
值将会被忽略,而后使用 minPoolSize
来替代。
在minPoolSize
和maxPoolSize
的范围以内,池中的链接数量与使用模式(usage patterns)有关。当用户请求一个链接,池中又没有可用链接,而且池中的链接数量还未达到maxPoolSize
的时候,池中的链接数就会增加。由于获取链接很是慢,因此成批地增长链接数量一般都颇有效,而不是强制要用户在须要新链接时从头开始激活并获取一个链接。acquireIncrement
属性决定了c3p0在没有可用链接时一次性获取的新链接数量。(不过c3p0毫不会所以而使链接数超过maxPoolSize
值。)
当链接池测试一个链接而且发现它已失效(broken)(参考下面的配置链接测试),或者当一个链接因空闲期超过一段时间而过时,或太旧(too old)(参考管理池尺寸和链接寿命)的时候,链接池中的链接数量将会降低。
C3P0 提供了大量的选项来控制池内链接数的增加或减少的速度,也能够用一些选项来决定“旧”链接是否应该主动地被替换以维持应用的可靠性。
maxConeectionAge
maxIdleTime
maxIdleTimeExcessConeections
默认状况下,链接池不会给链接设定过时时间。若是你为了保持链接“新鲜”,想要给
链接设定过时时间的话,须要设定 maxIdleTime
和/或 maxConnectionAge
。maxIdleTime
定义了链接因在多少秒内未被使用而被链接池剔除的时间。maxConnectionAge
决定了全部从数据库中获取的链接将在多少秒后被链接池剔除。
maxIdleTimeExcessConnections
用来最小化 c3p0 欠载(under load)时的链接数。默认状况下,在 c3p0 欠载时,c3p0 只会因链接测试失败或者链接过时而缩小池中的链接数。有一些用户须要在一些忽然增大会链接数的操做以后快速地释放没必要要的链接。你能够经过把maxIdleTimeExcessConnetions
设定为一个比 maxIdleTime
小得多的值来达到这个目的。超过最小链接数的那些链接会在较小的一段空闲时间以后被链接池剔除。
对设置这类超时参数有一些普通的建议:悠着点!使用链接池的重点就是尽可能只从数据库中获取链接一次,而后不断重复地使用它们。大多数的数据库的链接能够一次维持若干小时。没有必要每隔几秒钟或几分钟就剔除那些空闲的链接。把maxConnectionAge
或maxIdleTime
设置成 1800 (30 分钟)都是有些激进的。对于大多数数据库来说,几个小时或许更加合理。你能够用链接测试来确保可靠性,而不是一味地剔除它们(见配置链接测试)。一般只有 maxIdleTimeExcessConnetions
这个参数能够被设置成几分钟或更短的时间。
c3p0 的链接测试能够用来最小化你的应用遇到失效或过期的链接的可能性,它能够用
多种方式来进行配置。池中的链接可能会由于各类缘由而变得不可用——有些 JDBC 驱动有意地对长链接设置了超时参数;后端的数据库或网络有时候会宕掉;有些链接仅仅是由于资源紧缺,驱动的漏洞或者其余缘由而变得不可用。
c3p0 经过如下参数为用户提供了灵活的测试链接的方法:
automaticTestTable
connectionTesterClassName
idleConnectionTestPeriod
preferredTestQuery
testConnectionOnCheckin
testConnectionOnChechout
idleConnetionTestPeriod
, testConnectionOnCheckout
和testConnectionOnCheckin
决定了链接什么时候被测试。automaticTestTable
,connectionTesterClassName
和 preferredTestQuery
决定了链接怎样被测试。
当配置链接测试的时候,首先应该考虑如何减小测试的开支。默认状况下,链接经过在
与其关联的 DatabaseMetaData
对象上调用 getTables()
方法来进行测试。这对全部数据库来说都有效,由于这与数据库的视图(database schema)无关。然而,从经验上来说,调用DatabaseMetaData.getTables()
方法相对于进行一个简单的数据库查询要慢多了。
提升链接测试速度的最方便的方法就是定义 automaticTestTable
属性。c3p0 将会使用你提供的名字建立一个空的表,而后经过一个简单的查询来测试数据库。你也能够经过设定preferredTestQuery
参数来定义一个测试语句。不过你得小心点,设置 preferredTestQuery
将会致使在初始化数据源以前出现错误,若是你查询的目标表不存在的话。
高级用户能够实现一个 ConnectionTester
然 后 提 供 一 个 类 的 全 限 定 名 做 为connectionTesterClassName
属 性 来 实 现 任 何 想 要 的 连 接 测 试 。 如 果 你 想 要 使 你 的ConnectionTester
能 够 支 持 preferredTestQuery
和automaticTestTable
属 性 , 实 现UnifiedConnectionTester
接口便可,实现AbstractConnectionTester
是最方便的。更多信息见API 文档。
检测链接最可靠的时间就是从池中取出链接的时候(check-out)。但从客户端性能的角度 来 看 , 是 这 也 是 开 销 最 大 的 。 大 多 数 应 用 将 idleConnectionTestPeriod
和testConnectionOnCheckIn
结合起来用就已经很是可靠了。空闲测试和将链接放回池时(check-in)的测试都是异步执行的,这就是为何它们有更好的性能的缘由。
注意,对有些应用程序来讲,拥有高性能远比避免偶然发生的数据库异常更重要。默认
状况下,c3p0 不会作任何链接测试。设置一个很是长的idleConnectionTestPeriod
值和避免check-out 与 check-out 测试是很不错的,高性能的方法。
c3p0 实现了符合 JDBC 规范的透明的 PreparedStatement
池。在一些状况下,Statement
池可以显著地提升应用程序的性能。但在另外一些状况下,Statement
池的开销又会稍微的下降性能。
statement
到底能不能改善性能或者可以改善多少性能仍是取决于你的数据库对查询的解析,规划和优化(parsing, planning , and optimizing)。不一样数据库(和 JDBC 驱动)之间在这个方面存在很大的差别。给你的应用程序在使用和不使用statement
池的时候设定基准,而后比较它们来看看究竟statement
能不能改善性能是个不错的点子。
你能够经过设置下面的配置参数来配置 statement
池:
maxStatement
maxStatementPerConnection
maxStatement
是 JDBC 规范的标准参数。maxStatement
定义了每一个数据源会缓存的PreparedStatement
的总数。池内的Statement
总数在达到这个限制时会销毁那些最近最近最少使用的(least-recently-used)Statement
。这听起来很简单,不过事实上有些奇怪,由于从概念上来说,被缓存的 Statement
是属于单个的数据库链接的,它们并非全局资源。为了弄清楚maxStatements
的大小,你不该该简单地认为它就是池中 statement
的数量,你应该将你的应用程序中的最经常使用的PreparedStatement
的数量乘以合理的链接数(好比在一个高负荷的应用中的 maxPoolSize
值)。
maxStatementsPerConnection
不是一个标准的配置参数,这可能会使你感受有些不天然。它定义了链接池中每一个链接最多能拥有(缓存)多少 Statement
。为了不过多的折腾,你能够把这个值设为稍大于你应用中的 PreparedStatements
数量的一个数字。
这两个值中的任何一个大于 0 的话, statement
池就会被开启。若是两个参数都大于 0,它们的限制都会被强制执行。若是只有一个参数大于 0,仅仅只有一个限制会被强制执行。
c3p0 被设计成(而且默认开启了)能够从临时的数据库故障中恢复,好比数据库重启或者短暂地断开网络。你能够经过如下几个属性改变对 c3p0 在获取链接时遇到的错误的处理方式:
acquireRetryAttempts
acquireRetryDelay
breakAfterAcquireFailure
当 c3p0 在尝试获取数据库链接失败时,会自动地重试 acquireRetryAttempts
次,每次间隔 acquireRetryDelay
。若是依然失败,全部在等待这些链接的客户端将会收到一个异常,用来表示不能获取链接。请注意,若是不是全部的获取链接尝试都失败,客户端并不会收到异常,这可能在初始化尝试获取链接以后还须要一点儿时间。若是acquireRetryAttempts
被设置为0,c3p0将会无限期地尝试获取一个新的链接,对 getConnection()
的调用可能会无限阻塞下去,直到成功获取一个链接。
一旦全部的获取链接的尝试都失败,有两种可能的处理方式。默认状况下,c3p0 数据源会保持活性,而后对后续的请求做出回应。若是你将 breakAfterAcquireFailure 设置为 true的话,数据源将会在全部尝试失败后立刻中止工做,而且后续的请求也会立刻失败。
请注意,若是数据库重启了,一个链接池也许还维持着那些之前获取的而如今变得不可用的链接。默认状况下,这些陈旧的链接不会被立刻发现而且清理掉,当一个应用程序使用它们的时候,会立刻获得一个异常。设定 maxIdleTime
或者maxConnectionAge
能够帮助你加速替换掉这些不可用的链接。(见链接寿命的管理)若是你想彻底避免应用程序所以遇到异常,你必须得指定一中链接测试策略用来在客户端使用不可用链接以前就清理掉它们。(见链接测试的配置)即便使用积极的链接测试(testConnectionsOnCheckout
设置为true
,或者testConnectionsOnCheckin
为true
而且设置了一个小的 idleConnectionTestPeriod
值),你的应用程序在数据库重启的时候依然有可能遇到一个相关的异常,好比数据库在你已经将链接测试成功后才重启。
应用程序在获取链接后常常会但愿可以以某些标准的方法来重复地使用这些链接。例如,经过特定厂商的 APIs 或不标准的 SQL 扩展来设定字符编码或者日期时间等行为。有时候重写标准的链接中的默认属性值是颇有用的,好比重写 transactionIsolation
, holdbility
或者readOnly
。 c3p0 提供了一个“钩子”接口,你实现它就有机会在刚刚从数据库得到链接以后,在链接被送至客户端以前,在链接返回链接池以前,在链接最终被链接池淘汰以前,修改或追踪这个链接。交给ConnectionCustomizer
的链接是原生的,它全部的特定厂商的 API 均可以被访问。
ConnectionCustomizer
类的更多信息见 API 文档。
安装 ConnectionCustomizer
的方法就是实现这个接口,让其对 c3p0 的类加载器课件,而后设置下面这个配置属性:
connectionCustomizerClassName
ConnectionCustomizer
必须是不可变类,而且拥有一个没有参数的公开的构造方法。它不该该保存任何状态。(不多)有一些应用程序但愿使用 ConnectionCustomizer
来追踪单个的数据源的行为,这些与生命周期有关的方法都能接受一个特定的数据源的“实体令牌(identityToken)”做为参数,每一个 PooledDataSource
的实体令牌都是惟一的。
下面是一个简单的 ConnectionCustomizer
。实现类没有必要重写 ConnectionCustomizer
接口中的全部的四个方法,只须要继承 AbstractConnectionCustomizer
类就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import com.mchange.v2.c3p0.*; import java.sql.Connection; public class VerboseConnectionCustomizer{ public void onAcquire( Connection c, String pdsIdt ){ System.err.println("Acquired " + c + " [" + pdsIdt + "]"); // override the default transaction isolation of // newly acquired Connections c.setTransactionIsolation( Connection.REPEATABLE_READ ); } public void onDestroy( Connection c, String pdsIdt ){ System.err.println("Destroying " + c + " [" + pdsIdt + "]"); } public void onCheckOut( Connection c, String pdsIdt ){ System.err.println("Checked out " + c + " [" + pdsIdt + "]"); } public void onCheckIn( Connection c, String pdsIdt ){ System.err.println("Checking in " + c + " [" + pdsIdt + "]"); } } |
链接池中被检查过的链接不能有任何未结束的事务与其相关联。若是用户把一个链接的
autoCommit
属性设置成 false
,而且 c3p0 不能保证在这个链接上没有后续的事务工做的话,c3p0 就会在 check-in (当用户调用close()
方法)的时候调用rollback()
方法或者 commit()
方法。
JDBC 在有未结束事务的链接关闭时是应该回滚事务仍是应该提交事务这个问题上保持了沉默(这简直不可原谅)。在默认状况下,c3p0 会当用户在有未结束事务的链接上调用 close()方法时回滚事务。
你能够经过下面的配置参数更改这些相关行为:
autoCommitOnClose
foreIgnoreUnresolvedTransactions
若是你想要 c3p0 在链接返回链接池时(checkin )提交未结束的事务,只须要把
autoCommitOnClose
设置为 true。若是你但愿本身管理这些未结束的事务的话(而且没有设置链接的 autoCommit 属性), 你能够把forceIgnoreUnresolvedTransactions
设置为 true
。咱们强烈地不鼓励设置 forceIgnoreUnresolvedTransactions
的值,由于若是客户端在链接关闭前即没有回滚也没有提交事务,而且也没有开启自动提交的话,一些奇怪的不可再生的行为(unreproduceable behavior)和数据库被锁住的现象会发生。
有时候客户端应用程序对关闭链接这种工做很马虎。因而最后池内链接数增加到了maxPoolSize
,而后就用尽了全部链接,这种结果是这些有问题得客户端形成的。解决这个问题的正确的方法就是修复这些客户端程序。c3p0 能够帮助你找到那些偶尔不能正确地返回链接池的链接。在一些极少见而且不幸的状况下,即便你关闭了有漏洞的应用程序,你也修复不了它。c3p0 可以帮你解决这些问题。
下面的几个参数能够帮助你调试和解决有问题得客户端程序。
debugUnreturnedConnectionsStackTraces
unreturnedConnectionTimout
unreturnedConnectionTimeout
决定了从池中取出的链接能维持多少秒。 若是这个值非零,那么从池中取出的那些在超过这个限制时间的链接尚未返回池得话,就会被马上销毁,而后在池中被替代。很显然,你必需要保证这个参数的值可以让链接有时间完成那些应该作的工做。你能够用这个参数来解决那些关闭链接失败的不可靠的客户端程序。
完 全 修 复 漏 洞 要 比 仅 仅 使 应 用 恢 复 正 常 工 做 要 好 得 多 。 除 了 设 置 了unreturnedConnectionTimeout
以外,若是你还把 debugUnreturnedConnectionStackTraces
设置为true
的话,你将能够获得那些从池中取出的链接的轨迹栈(stack trace)。当有链接没有按时返回池的时候,轨迹栈将会被打印出来,来揭示哪里有链接没有按时返回。
c3p0引发了许多线程(helper threads,java.util.Timer.threads),并迟于应答池数据源的首次客户请求。默认状况下,c3p0引起的线程从这个第一次调用的线程中继承了java.security.AccessControlContext和contextClassLoader的特性。若是该线程来自某个须要热取消部署的客户端,这些引用可能会被划分为一个ClassLoader以避免被垃圾回收而终止取消部署程序。
c3p0提供了两个相关的参数:
contextClassLoaderSource应当设置一个caller或library或为空。(默认是一个caller)若是使用c3p0的ClassLoader将它设置为一个library,那么须要重部署的客户端将再也不包含引用。
privilegeSpawndThreads是一个默认为false的布尔值。若将它设置为true,那么c3p0的线程将使用c3p0库中的AccessControlContext,而不是可能和客户端程序相关联从而阻止垃圾回收的 AccessControlContext。
在附录中查看如下几个配置参数的更多信息:
checkoutTimeout
factoryClassLocation
maxAdminisrativeTaskTime
numHelperThreads
usesTraditionalReflectiveProxies
numHelperThreads
和 maxAdministrativeTaskTime
帮助你配置数据源线程池的行为。默认状况下,每一个数据源仅有三个助手线程(helper threads)。若是性能看起来被高负荷工做拖慢,或者你经过 JMX 观察到或直接检测出了“附加任务(pending tasks)”数量超过了0 的话,把numHelperThreads
的值提升试试吧。
maxAdministrativeTaskTime
可能对那些面临无限挂起的任务或者出现明显的死锁信息的用户有帮助。(更多信息见附录)
若是全部的链接都从池中取了出去,客户端不能当即获得链接的话,checkoutTimeout
限制了客户端会为获得一个链接等待多久。usesTraditionalReflectiveProxies
这个参数不多用到,它将容许你使用一种陈旧的,如今已经被取代的由 C3P0 生成的代理对象。(C3P0 之前使用反射和动态代理,而如今为了提高性能,使用了字节码生成,非反射的实现。 )若是客户端没有在本地安装 c3p0,而且 c3p0 的数据源是以一种引用的形式从 JNDI 里获得的,factoryClassLocation
就能用来甄别 c3p0 的哪些类是能够被下载下来的。
若是在你的环境中有 JMX 类库和 JMX MbeanServer
(它们在 JDK 1.5 以上版本已经被包括了进去),你能够经过 JMX 管理工具(好比 JDK 1.5 内置的 jconsole)来检测和配置 c3p0。你会发现 c3p0 在 com.mchange.v2.c3p0
下注册了不少 MBean
,有一个MBean
是整个库的汇总(叫作 C3P0Registry
),每一个你部署的 PooledDataSource
也对应着一个MBean
。你能够经过这个 PooledDataSource
的MBean
来查看或者修改你的配置信息,追踪链接、Statement
、线程池和其余的池与数据源的活动。(你可能须要查看 PoolDataSource
的 API 文档来获取它的可用的操做。)
c3p0中名为PooledDataSources
的mbeans
将会连同dataSourceName
属性一同注册。若是你配置了这个属性,能够确保语义等价的数据源在程序重启时是可分辨的。
若是你但愿从单个MBean server
中监控多个c3p0设施,你能够自定义JMX中出现的C3P0Registry
下的名称。你能够c3p0.properties
配置文件或HOCON config
中这样来配置系统文件:
1 |
com.mchange.v2.c3p0.management.RegistryName=myRegistryName |
若是你不须要 c3p0 在你的 JMX 环境下注册 MBean
,你能够c3p0.properties
配置文件或HOCON config
中这样来配置系统文件:
1 |
com.mchange.v2.c3p0.management.ManagementCoordinator=com.mchange.v2.c3p0.management.NullManagementCoordinator |
c3p0 使用了一种与 jakarta commons-logging
很类似的日志类库。日志信息能够传给流行的日志类库 log4j
, JDK 1.4 中推荐的标准日志设备或者 System.err
。差很少全部的配置均可以在你喜欢的那些高层的日志类库中完成。只有少数几个配置是 c3p0 的日志所特有的,而且使用默认配置就好了。和日志相关的配置参数可能在你的c3p0.properties
文件里,或者在你CLASSPATH
的顶级目录中的 mchange-log.properties
文件里,也有可能在系统属性里定义。(下面的日志配置参数可能不能在 c3p0-config.xml
中定义!)。见下面的文本框。
c3p0 的日志行为会被一些编译期选项(build-time options)影响。若是编译期选项c3p0.debug
被设置成 false
,全部低于INFO
级别的日志信息将会被忽略。编译期选项 c3p0.trace
可以控制低于 INFO
级别的日志信息的报告颗粒细度。目前来说,c3p0 的发行版本的二进制文件都是把 debug
设置成true
,把 trace
设置成最大值 10 来进行编译的。不过最终可能会在发行版中把 debug
设置为 false
。[就目前来说,日志级别检查(logging level-checks)对性能的影响是很小的, 编译期间对这些信息的控制都至关灵活,你也可以让你的日志类库来控制哪些信息是要被记录的。]当 c3p0 启动的时候,那些 debug
和 trace
的编译期的值也会随着版本和编译时间被记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
com.mchange.v2.log.MLog Determines which library c3p0 will output log messages to. By default, if log4j is available, it will use that library, otherwise if jdk1.4 logging apis are available it will use those, and if neither are available, it will use a simple fallback that logs to System.err. If you want to directly control which library is used, you may set this property to one of: com.mchange.v2.log.log4j.Log4jMLog com.mchange.v2.log.slf4j.Slf4jMLog com.mchange.v2.log.jdk14logging.Jdk14MLog com.mchange.v2.log.FallbackMLog Alternatively, the following abbreviations are supported: log4j slf4j jul, jdk14, java.util.logging fallback You may also set this property to a comma separated list of any mix the above alternatives, to define an order of preference among logging libraries. com.mchange.v2.log.jdk14logging.suppressStackWalk Under JDK standard logging, the logging library may inspect stack traces to determine the class and method from which a log message was generated. That can be helpful, but it is also slow. Setting this configuration parameter to true will suppress this stack walk, and reduce the overhead of logging. This property now defaults to true, and logger names are logged in place of class names. To return to the original slower but more informative approach, explicitly set the property to false. com.mchange.v2.log.NameTransformer By default, c3p0 uses very fine-grained logging, in general with one logger for each c3p0 class. For a variety of reasons, some users may prefer fewer, more global loggers. You may opt for one-logger-per-package by setting com.mchange.v2.log.NameTransformer to the value com.mchange.v2.log.PackageNames. Advanced users can also define other strategies for organizing the number and names of loggers by setting this variable to the fully-qualified class name of a custom implementation of the com.mchange.v2.log.NameTransformer interface. com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL If, whether by choice or by necessity, you are using c3p0's System.err fallback logger, you can use this parameter to control how detailed c3p0's logging should be. Any of the following values (taken from the jdk1.4 logging library) are acceptable: OFF SEVERE WARNING INFO CONFIG FINE FINER FINEST ALL This property defaults to INFO. |
你能够定义命名配置以扩充和重写定义的默认配置。当你实例化一个c3p0池化数据源时,不管是经过ComboPooledDataSource
构造器仍是经过DataSources
工厂类构造,你均可以替换它的名字。例如:
经过ComboPooledDataSource
:
1 |
ComboPooledDataSource cpds = new ComboPooledDataSource("intergalactoApp"); |
经过DataSources工厂类:
1 |
DataSource ds_pooled = DataSources.pooledDataSource( ds_unpooled, "intergalactoApp" ); |
你能够这样定义命名配置:
在属性类型的配置文件中:
1 2 3 4 5 6 7 8 9 10 11 12 |
# define default-config param values c3p0.maxPoolSize=30 c3p0.minPoolSize=10 # define params for a named config called intergalactoApp c3p0.named-configs.intergalactoApp.maxPoolSize=1000 c3p0.named-configs.intergalactoApp.minPoolSize=100 c3p0.named-configs.intergalactoApp.numHelperThreads=50 # define params for a named config called littleTeenyApp c3p0.named-configs.littleTeenyApp.maxPoolSize=5 c3p0.named-configs.littleTeenyApp.minPoolSize=2 |
在HOCON配置文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
c3p0 { maxPoolSize=30 minPoolSize=10 named-configs { intergalactoApp { maxPoolSize=1000 minPoolSize=100 numHelperThreads=50 } littleTeenyApp { maxPoolSize=5 minPoolSize=2 } } } |
在XML配置文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<c3p0-config> <default-config> <property name="maxPoolSize">30</property> <property name="minPoolSize">10</property> </default-config> <named-config name="intergalactoApp"> <property name="maxPoolSize">1000</property> <property name="minPoolSize">100</property> <property name="numHelperThreads">50</property> </named-config> <named-config name="littleTeenyApp"> <property name="maxPoolSize">5</property> <property name="minPoolSize">2</property> </named-config> </c3p0-config> |
你能够为某个特定用户已验证的池链接定义默认或命名配置的重写方法。并不是全部的配置参数都支持各用户的方法重写。详情可见附录。
你能够这样定义各用户配置:
在属性类型的配置文件中:
1 2 3 4 5 6 7 8 9 10 11 |
# define default-config param values c3p0.maxPoolSize=30 c3p0.minPoolSize=10 # define params for a user called 'steve' c3p0.user-overrides.steve.maxPoolSize=15 c3p0.user-overrides.steve.minPoolSize=5 # define params for a user called 'ramona' c3p0.user-overrides.steve.maxPoolSize=50 c3p0.user-overrides.steve.minPoolSize=20 |
在HOCON配置文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
c3p0 { maxPoolSize=30 minPoolSize=10 user-overrides { steve { maxPoolSize=15 minPoolSize=5 } ramona { maxPoolSize=50 minPoolSize=20 } } } |
在XML配置文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<c3p0-config> <default-config> <property name="maxPoolSize">30</property> <property name="minPoolSize">10</property> <user-overrides user="steve"> <property name="maxPoolSize">15</property> <property name="minPoolSize">5</property> </user-overrides> <user-overrides user="ramona"> <property name="maxPoolSize">50</property> <property name="minPoolSize">20</property> </user-overrides> </default-config> </c3p0-config> |
用户能够添加自定义的配置信息,一般是定制的ConnectionCustomizers
行为。用户自定义的配置存储为一个包含了String
键和值的Map
,存储在如下配置参数中:
extensions
这个扩展Map
能像其余的配置参数同样经过编程来配置。不过,定义这个扩展Map
的键和值有着特殊的配置文件支持:
在属性类型的配置文件中:
1 2 3 |
c3p0.extensions.initSql=SET SCHEMA 'foo' c3p0.extensions.timezone=PDT ... |
在HOCON配置文件中:
1 2 3 4 5 6 |
c3p0 { extensions { initSql=SET SCHEMA 'foo' timezone=PDT } } |
在XML配置文件中:
1 2 3 4 5 6 7 8 |
<c3p0-config> <default-config> <extensions> <property name="initSql">SET SCHEMA 'foo'</property> <property name="timezone">PDT</property> </extensions> </default-config> </c3p0-config> |
为了找到池化数据源的扩展定义,你必须得到它的identityToken
权限,这在全部ConnectionCustomizer
中都做为一个参数被提供。得到了identityToken
权限,你就能够经过使用C3P0Registry.extensionsForToken(...)
方法来获取扩展Map
。
因为这些扩展主要被设计用于ConnectionCustomizer
的实现,AbatractConnectionCustomizer
类一样定义了一个protected extensionForToken(...)
方法。
下面是一个使用了用户自定义配置扩展的ConnectionCustomizer
实现。它定义了一个initSql
扩展,这个扩展的值应当是String类型的包含应当在Connection
被池容许时执行的SQL语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package mypkg; import java.sql.*; import com.mchange.v2.c3p0.AbstractConnectionCustomizer; public class InitSqlConnectionCustomizer extends AbstractConnectionCustomizer{ private String getInitSql( String parentDataSourceIdentityToken ){ return (String) extensionsForToken( parentDataSourceIdentityToken ).get ( "initSql" ); } public void onCheckOut( Connection c, String parentDataSourceIdentityToken) throws Exception{ String initSql = getInitSql( parentDataSourceIdentityToken ); if ( initSql != null ){ Statement stmt = null; try{ stmt = c.createStatement(); stmt.executeUpdate( initSql ); } finally{ if ( stmt != null ) stmt.close(); } } } } |
命名配置、各用户重写以及用户自定义配置扩展能够很方便地结合起来:
在属性类型的配置文件中:
1 2 3 4 5 6 |
c3p0.maxPoolSize=30 c3p0.extensions.initSql=SET SCHEMA 'default' c3p0.named-configs.intergalactoApp.maxPoolSize=1000 c3p0.named-configs.intergalactoApp.extensions.initSql=SET SCHEMA 'intergalacto' c3p0.named-configs.user-overrides.steve.maxPoolSize=20 |
在HOCON配置文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
c3p0 { maxPoolSize=30 extensions { initSql=SET SCHEMA 'default' } named-configs { intergalactoApp { maxPoolSize=1000 user-overrides { steve { maxPoolSize=20 } } extensions { initSql=SET SCHEMA 'intergalacto' } } } } |
在XML配置文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<c3p0-config> <default-config> <property name="maxPoolSize">30</property> <extensions> <property name="initSql">SET SCHEMA 'default'</property> </extensions> </default-config> <named-config name="intergalactoApp"> <property name="maxPoolSize">1000</property> <user-overrides name="steve"> <property name="maxPoolSize">20</property> </user-overrides> <extensions> <property name="initSql">SET SCHEMA 'intergalacto'</property> </extensions> </named-config> </c3p0-config> |
加强性能,是链接池、 Statement
池以及 c3p0 类库的主要目的。对大多数应用程序来讲,链接池会使得性能显著提升,特别是当你给每一个客户端访问每次都从新获取链接的话。 若是你让单个的共享的链接来为多个客户端服务以免过多的链接获取工做的话,那么你在多线程的环境下可能会遇到性能或者事物管理问题;链接池将会可以让你有机会选择不多或没有开销的单客户端单链接模型(One Connection-per client model)。 若是你正在编写企业级 Java Bean,你可能会想要只获取一次链接而后并不返回它,直到它被销毁或者过期。 可是这样作太耗费资源了,由于这些 Bean 没必要要的占用了链接网络和数据库资源。链接池容许 Bean只在使用链接时才占有链接。
可是,c3p0 也有性能上的开销。为了实现当父资源返回池得时候自动清理未被关闭的
ResultSet
和 Statement
,全部客户端可见的 Connection
,ResultSet
,Statement
都封装了那些底层的数据源或者“传统的”JDBC 驱动。所以,全部 JDBC 调用都会有一些额外的开销。
c3p0 在减少“封装”所带来的性能开销方面下了一些工夫。在个人环境中,由包装所带来的性能问题来自成百上千的数据库获取操做。因此,你应该从 c3p0 中获得的是性能的提高和高效的资源利用,除非你快速地轮载(succession)了不少不少 JDBC 调用。很显然,与结果集相关操做(好比要在其上遍历一个有上千条记录的表)带来的开销是能够忽略不计的。
API文档见:
http://www.mchange.com/projects/c3p0/apidocs/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
<c3p0-config> <default-config> <!--当链接池中的链接耗尽的时候c3p0一次同时获取的链接数。Default: 3 --> <property name="acquireIncrement">3</property> <!--定义在从数据库获取新链接失败后重复尝试的次数。Default: 30 --> <property name="acquireRetryAttempts">30</property> <!--两次链接中间隔时间,单位毫秒。Default: 1000 --> <property name="acquireRetryDelay">1000</property> <!--链接关闭时默认将全部未提交的操做回滚。Default: false --> <property name="autoCommitOnClose">false</property> <!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。若是定义了这个参数那么 属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操做,它将只供c3p0测试 使用。Default: null--> <property name="automaticTestTable">Test</property> <!--获取链接失败将会引发全部等待链接池来获取链接的线程抛出异常。可是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取链接。若是设为true,那么在尝试 获取链接失败后该数据源将申明已断开并永久关闭。Default: false--> <property name="breakAfterAcquireFailure">false</property> <!--当链接池用完时客户端调用getConnection()后等待获取新链接的时间,超时后将抛出 SQLException,如设为0则无限期等待。单位毫秒。Default: 0 --> <property name="checkoutTimeout">100</property> <!--经过实现ConnectionTester或QueryConnectionTester的类来测试链接。类名需制定全路径。 Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester--> <property name="connectionTesterClassName"></property> <!--指定c3p0 libraries的路径,若是(一般都是这样)在本地便可得到那么无需设置,默认null便可 Default: null--> <property name="factoryClassLocation">null</property> <!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs. (文档原文)做者强烈建议不使用的一个属性--> <property name="forceIgnoreUnresolvedTransactions">false</property> <!--每60秒检查全部链接池中的空闲链接。Default: 0 --> <property name="idleConnectionTestPeriod">60</property> <!--初始化时获取三个链接,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> <property name="initialPoolSize">3</property> <!--最大空闲时间,60秒内未使用则链接被丢弃。若为0则永不丢弃。Default: 0 --> <property name="maxIdleTime">60</property> <!--链接池中保留的最大链接数。Default: 15 --> <property name="maxPoolSize">15</property> <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但因为预缓存的statements 属于单个connection而不是整个链接池。因此设置这个参数须要考虑到多方面的因素。 若是maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0--> <property name="maxStatements">100</property> <!--maxStatementsPerConnection定义了链接池内单个链接所拥有的最大缓存statements数。Default: 0 --> <property name="maxStatementsPerConnection"></property> <!--c3p0是异步操做的,缓慢的JDBC操做经过帮助进程完成。扩展这些操做能够有效的提高性能 经过多线程实现多个操做同时被执行。Default: 3--> <property name="numHelperThreads">3</property> <!--当用户调用getConnection()时使root用户成为去获取链接的用户。主要用于链接池链接非c3p0 的数据源时。Default: null--> <property name="overrideDefaultUser">root</property> <!--与overrideDefaultUser参数对应使用的一个参数。Default: null--> <property name="overrideDefaultPassword">password</property> <!--密码。Default: null--> <property name="password"></property> <!--定义全部链接测试都执行的测试语句。在使用链接测试的状况下这个一显著提升测试速度。注意: 测试的表必须在初始数据源的时候就存在。Default: null--> <property name="preferredTestQuery">select id from test where id=1</property> <!--用户修改系统配置参数执行前最多等待300秒。Default: 300 --> <property name="propertyCycle">300</property> <!--因性能消耗大请只在须要的时候使用它。若是设为true那么在每一个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable 等方法来提高链接测试的性能。Default: false --> <property name="testConnectionOnCheckout">false</property> <!--若是设为true那么在取得链接的同时将校验链接的有效性。Default: false --> <property name="testConnectionOnCheckin">true</property> <!--用户名。Default: null--> <property name="user">root</property> <!--早期的c3p0版本对JDBC接口采用动态反射代理。在早期版本用途普遍的状况下这个参数 容许用户恢复到动态反射代理以解决不稳定的故障。最新的非反射代理更快而且已经开始 普遍的被使用,因此这个参数未必有用。如今原先的动态反射与新的非反射代理同时受到 支持,但从此可能的版本可能不支持动态反射代理。Default: false--> <property name="usesTraditionalReflectiveProxies">false</property> <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">25</property> <property name="minPoolSize">10</property> <property name="maxStatements">0</property> <user-overrides user="swaldman"> </user-overrides> </default-config> <named-config name="dumbTestConfig"> <property name="maxStatements">200</property> <user-overrides user="poop"> <property name="maxStatements">300</property> </user-overrides> </named-config> </c3p0-config> |
Hibernate的C3P0ConnectionPtovider
重命名了7个c3p0配置属性,若是你在Hibernate中设置了它们,将覆盖全部可能在c3p0.properties
文件中的配置。
c3p0本地属性名 | Hibernate配置键 |
---|---|
c3p0.acquireIncrement |
hibernate.c3p0.acquire_increment |
c3p0.idleConnectionTestPeriod |
hibernate.c3p0.idle_test_period |
c3p0.initialPoolSize |
未提供,使用最小值 |
c3p0.maxIdleTime |
hibernate.c3p0.timeout |
c3p0.maxPoolSize |
hibernate.c3p0.max_size |
c3p0.maxStatements |
hibernate.c3p0.max_statements |
c3p0.minPoolSize |
hibernate.c3p0.min_size |
c3p0.testConnectionOnCheckout |
hibernate.c3p0.validate (仅用于Hibernate 2.x) |
你能够在Hibernate配置中使用hibernate.c3p0
前缀来设置任何c3p0属性。例如:
1 2 |
hibernate.c3p0.unreturnedConnectionTimeout=30 hibernate.c3p0.debugUnreturnedConnectionStackTraces=true |
在JBoss中使用c3p0:
${JBOSS_HOME}/server/default/lib
)${JBOSS_HOME}/server/default/deploy
)定义并保存c3p0-service.xml
文件。参数必须大写: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE server> <server> <mbean code="com.mchange.v2.c3p0.jboss.C3P0PooledDataSource" name="jboss:service=C3P0PooledDataSource"> <attribute name="JndiName">java:PooledDS</attribute> <attribute name="JdbcUrl">jdbc:postgresql://localhost/c3p0-test</attribute> <attribute name="DriverClass">org.postgresql.Driver</attribute> <attribute name="User">swaldman</attribute> <attribute name="Password">test</attribute> <!-- Uncomment and set any of the optional parameters below --> <!-- See c3p0's docs for more info. --> <!-- <attribute name="AcquireIncrement">3</attribute> --> <!-- <attribute name="AcquireRetryAttempts">30</attribute> --> <!-- <attribute name="AcquireRetryDelay">1000</attribute> --> <!-- <attribute name="AutoCommitOnClose">false</attribute> --> <!-- <attribute name="AutomaticTestTable"></attribute> --> <!-- <attribute name="BreakAfterAcquireFailure">false</attribute> --> <!-- <attribute name="CheckoutTimeout">0</attribute> --> <!-- <attribute name="ConnectionCustomizerClassName"></attribute> --> <!-- <attribute name="ConnectionTesterClassName"></attribute> --> <!-- <attribute name="Description">A pooled c3p0 DataSource</attribute> --> <!-- <attribute name="DebugUnreturnedConnectionStackTraces">false</attribute> --> <!-- <attribute name="FactoryClassLocation"></attribute> --> <!-- <attribute name="ForceIgnoreUnresolvedTransactions">false</attribute> --> <!-- <attribute name="IdleConnectionTestPeriod">0</attribute> --> <!-- <attribute name="InitialPoolSize">3</attribute> --> <!-- <attribute name="MaxAdministrativeTaskTime">0</attribute> --> <!-- <attribute name="MaxConnectionAge">0</attribute> --> <!-- <attribute name="MaxIdleTime">0</attribute> --> <!-- <attribute name="MaxIdleTimeExcessConnections">0</attribute> --> <!-- <attribute name="MaxPoolSize">15</attribute> --> <!-- <attribute name="MaxStatements">0</attribute> --> <!-- <attribute name="MaxStatementsPerConnection">0</attribute> --> <!-- <attribute name="MinPoolSize">0</attribute> --> <!-- <attribute name="NumHelperThreads">3</attribute> --> <!-- <attribute name="PreferredTestQuery"></attribute> --> <!-- <attribute name="TestConnectionOnCheckin">false</attribute> --> <!-- <attribute name="TestConnectionOnCheckout">false</attribute> --> <!-- <attribute name="UnreturnedConnectionTimeout">0</attribute> --> <!-- <attribute name="UsesTraditionalReflectiveProxies">false</attribute> --> <depends>jboss:service=Naming</depends> </mbean> </server> |
Oracle JDBC驱动提供了一个非标准的API以建立临时BLOB
和CLOB
,用户必须对原始的Oracle特定链接实例调用方法。进阶用户可能用如上描述原始的链接操做来实现这个功能,但在一个单独的jar文件(c3p0-oracle-thin-extras-0.95-pre8.jar
)中,提供了一个方便的类。你能够查询com.mchange.v2.c3p0.dbms.OracleUtils
中的API文档获取详细信息。
在Apache的Tomcat网络应用服务中配置c3p0池数据源是很容易的。如下是一个Tomcat 5.0的案例,它是Tomcat中conf/server.xml
文件中的一部分,应当被修改以适应置于<Context>
元素中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<Resource name="jdbc/pooledDS" auth="Container" type="com.mchange.v2.c3p0.ComboPooledDataSource" /> <ResourceParams name="jdbc/pooledDS"> <parameter> <name>factory</name> <value>org.apache.naming.factory.BeanFactory</value> </parameter> <parameter> <name>driverClass</name> <value>org.postgresql.Driver</value> </parameter> <parameter> <name>jdbcUrl</name> <value>jdbc:postgresql://localhost/c3p0-test</value> </parameter> <parameter> <name>user</name> <value>swaldman</value> </parameter> <parameter> <name>password</name> <value>test</value> </parameter> <parameter> <name>minPoolSize</name> <value>5</value> </parameter> <parameter> <name>maxPoolSize</name> <value>15</value> </parameter> <parameter> <name>acquireIncrement</name> <value>5</value> </parameter> </ResourceParams> |
对于Tomcat 5.5,使用如下配置:
1 2 3 4 5 6 7 8 9 10 11 12 |
<Resource auth="Container" description="DB Connection" driverClass="com.mysql.jdbc.Driver" maxPoolSize="4" minPoolSize="2" acquireIncrement="1" name="jdbc/TestDB" user="test" password="ready2go" factory="org.apache.naming.factory.BeanFactory" type="com.mchange.v2.c3p0.ComboPooledDataSource" jdbcUrl="jdbc:mysql://localhost:3306/test?autoReconnect=true" /> |
下面是一个标准的J2EE配置:你必须在你的web.xml文件中声明你的数据源。
1 2 3 4 5 |
<resource-ref> <res-ref-name>jdbc/pooledDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> |
而后你能够在你的网络应用中以下配置以访问你的数据源:
1 2 |
InitialContext ic = new InitialContext(); DataSource ds = (DataSource) ic.lookup("java:comp/env/jdbc/pooledDS"); |
Statement
是基于单个认证的。因此,若是一个链接池后端的数据源从[user=alice, password=secret1]
和[user=bob, password=secret2]
中获取链接的话,就至关于有两个不一样的池,因此在最坏的状况下,数据源可能要管理两套maxPoolSize
这么多数量的链接。这个问题是数据源规范(它容许从多个用户认证中获取链接)形成的结果,而且同一个池中的链接在功能上必须是一致的。因此这个“问题”不会被改变或者修复。这里提出来只是为了让你弄清楚究竟是怎么一回事。Statement
池的开销太大了。若是驱动不对PreparedStatement
执行明显的预处理,Statement
池的开销要大于它节省的时间。所以他默认是关闭的。若是你的驱动的确预处理了PreparedStatement
,特别是经过 IPC 与 RDBMS 的话,你将可能会从中得到很明显的性能提高。(经过把maxStatements
或maxStatementsPerConnection
的配置属性设置成比 0 大的数)