欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

【译文】c3p0使用介绍文档
(last modified Jun 26, 2023, 12:31 PM )
by
侧边栏壁纸
  • 累计撰写 176 篇文章
  • 累计创建 61 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

【译文】c3p0使用介绍文档

橙序员
2022-12-03 / 0 评论 / 0 点赞 / 761 阅读 / 27,166 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

使用文档原始地址:https://www.mchange.com/projects/c3p0/快速开始c3p0 被设计为简单易用。只需将文件lib/c3p0-0.9.5.5.jar和lib/mchange-commons-java-0.2.19.jar放入您的应用程序的有效CLASSPATH中,然后

使用文档原始地址:https://www.mchange.com/projects/c3p0/

快速开始

c3p0 被设计为简单易用。只需将文件lib/c3p0-0.9.5.5.jarlib/mchange-commons-java-0.2.19.jar放入您的应用程序的有效CLASSPATH中,然后制作一个像这样的数据源:

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):

cpds.setMaxStatements( 180 );

使用您的 DataSource 做任何您想做的事情,这将由使用默认参数设置的连接池支持。您可以根据需要将 DataSource 绑定到 JNDI 名称服务,或直接使用它。

完成后,您可以像这样清理您创建的数据源:

cpds.close();

而已!剩下的就是细节了。

什么是c3p0?

c3p0 是一个易于使用的库,用于通过使用 jdbc3 规范定义的功能和 jdbc2 的可选扩展来增强传统 JDBC 驱动程序,从而使它们“企业就绪”。从 0.9.5 版本开始,c3p0 完全支持 jdbc4 规范。

特别是,c3p0 提供了几个有用的服务:

  • 一个类,它使传统的基于 DriverManager 的 JDBC 驱动程序适应更新的javax.sql.DataSource方案以获取数据库连接。
  • DataSources 后面的 ConnectionPreparedStatements 的透明池化可以“环绕”传统驱动程序或任意未池化的 DataSources

图书馆努力使细节正确:

  • c3p0 DataSources 都是ReferenceableSerializable,因此适合绑定到各种基于 JNDI 的命名服务。
  • 当汇集的连接和语句被签入时,语句和结果集会被仔细清理,以防止在客户端使用惰性但常见的资源管理策略仅清理其连接时资源耗尽。(不要调皮。)
  • 该库采用 JDBC 2 和 3 规范定义的方法(即使这些与库作者的偏好有冲突)。DataSourcesJavaBean 风格编写,提供所有必需和大部分可选属性(以及一些非标准属性)和无参数构造函数。所有 JDBC 定义的内部接口都已实现(ConnectionPoolDataSource、PooledConnection、ConnectionEvent 生成的连接等)。您可以将 c3p0 类与兼容的第三方实现混合使用(尽管并非所有 c3p0 功能都适用于ConnectionPoolDataSource的外部实现)。

c3p0 希望提供更适合大容量“J2EE 企业应用程序”使用的 DataSource 实现。请提供反馈、错误修复等!

先决条件

c3p0-0.9.5.5 需要 1.6.x 或更高级别的 Java 运行时环境。

安装

将文件lib/c3p0-0.9.5.5.jarlib/mchange-commons-java-0.2.19.jar 放在您的 CLASSPATH 中的某个位置(或您的应用程序的类加载器可以找到它的任何其他位置)。而已!

使用 c3p0

从用户的角度来看,c3p0 只是提供标准的 jdbc DataSource 对象。创建这些数据源时,用户可以控制与池相关、命名相关和其他属性。(有关配置属性的完整列表,请参阅附录 A。)一旦创建了数据源,所有池对用户都是完全透明的。

获取 c3p0 pool-backed DataSources 的方式有以下三种:

  1. 直接实例化并配置一个 ComboPooledDataSource bean;

  2. 使用数据源工厂类

  3. 通过直接实例化PoolBackedDataSource并设置其ConectionPoolDataSource来“构建您自己的”池支持的 DataSource 。

大多数用户可能会发现实例化ComboPooledDataSource 是最方便的方法。一旦实例化,c3p0 数据源就可以绑定到几乎任何符合 JNDI 的名称服务。

无论您如何创建数据源,c3p0 都将为您未通过编程方式指定的任何配置参数使用其配置的默认值。c3p0 具有内置的、硬编码的默认值,但您可以使用配置文件覆盖这些默认值,并将其作为顶级资源放置在加载 c3p0 的 jar 文件 的同一CLASSPATH (或 ClassLoader)中。

c3p0 数据源可以通过 名为c3p0.properties的简单java.util.Properties文件、通过更高级 的 HOCON 配置文件 (例如application.confapplication.json)或 XML 格式 c3p0-config.xml进行配置。请参阅下面的配置

实例化和配置 ComboPooledDataSource

也许创建 c3p0 池化 DataSource 最直接的方法是实例化 com.mchange.v2.c3p0.ComboPooledDataSource的实例。这是一个 JavaBean 风格的类,带有一个公共的、无参数的构造函数,但在您使用 DataSource 之前,您必须确保至少设置属性jdbcUrl。您可能还想设置userpassword,并且,如果您使用不会在外部预加载的旧式 JDBC 驱动程序,则应该设置driverClass

ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "org.postgresql.Driver" ); //加载jdbc驱动类            
cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
cpds.setUser("swaldman");                                  
cpds.setPassword("test-password");                                  
	
// 以下配置为自定义 -- c3p0 也能通过默认参数工作
cpds.setMinPoolSize(5);                                     
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
	
// 数据源cpds现在已经配置完成并使用了池化的数据源

任何 c3p0 DataSource 属性的默认值由您提供的配置决定,或者恢复为硬编码默认值 [请参阅配置属性]。c3p0 支持命名配置,因此您可以配置多个数据源。如果您希望使用命名配置,请 使用配置名称作为构造函数参数构造您的 com.mchange.v2.c3p0.ComboPooledDataSource

ComboPooledDataSource cpds = new ComboPooledDataSource("intergalactoApp");

当然,您仍然可以像上面那样以编程方式来覆盖任何配置属性。

使用数据源工厂类

或者,您可以使用静态工厂类 com.mchange.v2.c3p0.DataSources从传统 JDBC 驱动程序构建非池化数据源,并从非池化数据源构建池化数据源:

DataSource ds_unpooled = DataSources.unpooledDataSource("jdbc:postgresql://localhost/testdb", 
                                                        "swaldman", 
                                                        "test-password");
DataSource ds_pooled = DataSources.pooledDataSource( ds_unpooled );

// 数据源cpds现在已经配置完成并使用了池化的数据源
// DataSource使用默认池配置,并且假定 Postgres 的 JDBC 驱动程序已经通过 jdbc.drivers 系统属性或在其他地方显式调用 Class.forName("org.postgresql.Driver") 加载。

如果你使用DataSources 工厂类,并且你想以编程方式覆盖默认配置参数,你可以提供覆盖属性的映射:

DataSource ds_unpooled = DataSources.unpooledDataSource("jdbc:postgresql://localhost/testdb", 
                                                        "swaldman", 
                                                        "test-password");
							      
Map overrides = new HashMap();
overrides.put("maxStatements", "200");         //支持字符串化的数值格式
overrides.put("maxPoolSize", new Integer(50)); //支持装箱

// 使用默认配置和我们的覆盖创建 PooledDataSource
ds_pooled = DataSources.pooledDataSource( ds_unpooled, overrides ); 

// DataSource ds_pooled 现在是一个完全配置和可用的池化 DataSource,启用了最多 200 个语句和最多 50 个连接的语句缓存。

如果您使用的是命名配置,则可以指定定义数据源默认配置的配置:

// 使用命名配置创建 PooledDataSource 并指定覆盖“intergalactoApp”是命名配置
ds_pooled = DataSources.pooledDataSource( ds_unpooled, "intergalactoApp", overrides ); 
弃用!通过 PoolConfig 进行编程配置

如果您使用DataSources 工厂类,并且想要以编程方式覆盖默认配置参数,请使用PoolConfig类:

DataSource ds_unpooled = DataSources.unpooledDataSource("jdbc:postgresql://localhost/testdb", 
                                                     "swaldman", 
                                                     "test-password");

PoolConfig pc = new PoolConfig();
pc.setMaxStatements(200);  //turn on Statement pooling

// pass our overriding PoolConfig to the DataSources.pooledDataSource() factory method.

ds_pooled = DataSources.pooledDataSource( ds_unpooled, pc ); 

// 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.

隐藏弃用的 PoolConfig 方法

罕见:强制验证信息,不管底层(未合并的)数据源的(错误)配置如何您可以使用DataSource.pooledDataSource( ... ) 包装任何 DataSouce ,通常没有任何问题。DataSources 应该通过标准属性userpassword 指示默认情况下与 Connections 关联的用户名和密码。某些 DataSource 实现不提供这些属性。通常这根本不是问题。如果c3p0找不到默认身份验证信息,并且客户端未通过 getConnection(user, password)指定身份验证信息,则 c3p0 通过从 DataSource 获取“默认”连接来解决此问题。然而,在极少数情况下,非 c3p0 未合并的数据源提供用户属性,但不提供密码属性,或者您可以访问希望包装在池后面的数据源,但您希望覆盖其内置身份验证默认值而不实际上修改用户 或密码属性。

c3p0提供配置属性overrideDefaultUseroverrideDefaultPassword。如果您设置这些属性,以编程方式如上所述,或通过任何 c3p0 的配置机制c3p0 PooledDataSources 将忽略与底层数据源关联的用户和密码属性,并使用指定的替代。

查询 PooledDataSource 的当前状态

由池支持的 c3p0 DataSources,包括 ComboPooledDataSource 的实现 DataSources .pooledDataSource( ... )返回的对象,都实现了接口 com.mchange.v2.c3p0.PooledDataSource,它提供了许多查询方法数据源连接池的状态。下面是查询 DataSource 状态的示例代码:

// 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.getNumBusyConnectionsDefaultUser());
  System.err.println("num_idle_connections: " + pds.getNumIdleConnectionsDefaultUser());
  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 为具有不同身份验证的连接维护单独的池。各种方法让您可以单独查询池的状态,或汇总数据源维护池的所有身份验证的统计信息。*请注意,诸如maxPoolSize 之类的池配置参数是在每次身份验证的基础上强制执行的!*例如,如果您将maxPoolSize设置为 20,并且如果 DataSource 正在管理两个用户名-密码对下的连接 [默认值,另一对是通过调用getConnection(user, password)建立的,您应该会看到来自getNumConnectionsAllUsers()的多达 40 个连接。

大多数应用程序仅从 DataSources 获取经过默认身份验证的连接,并且通常只能使用getXXXDefaultUser()来收集连接统计信息。

除了连接池相关的统计信息,您还可以检索有关每个数据源的线程池的状态信息。有关可用操作的完整列表,请参阅PooledDataSource

使用 C3P0Registry 获取对数据源的引用

如果通过 JNDI 或其他方式获取对数据源的引用不方便或不可能,您可以使用 C3P0Registry类找到所有活动的 c3p0 数据源,该类包括三个静态方法来帮助您:

  • public static Set getPooledDataSources()
  • public static Set pooledDataSourcesByName( String dataSourceName )
  • public static PooledDataSource pooledDataSourceByName( String dataSourceName )

第一种方法将把所有活动的 c3p0 PooledDataSources的集合交给你。如果您确定您的应用程序只生成一个PooledDataSources,或者您可以通过配置属性(通过“getters”检查)来区分 DataSources,则第一种方法可能就足够了。因为情况并非总是如此,c3p0 PooledDataSources有一个名为 dataSourceName的特殊属性。您可以在构建 DataSource 时直接设置dataSourceName属性,或者可以像命名配置或默认配置中的任何其他属性一样设置 dataSourceName。否则,dataSourceName将默认为:

  1. DataSource 配置的名称,如果您使用命名配置构建它;
  2. 一个唯一的(但不可预测的)名称,如果您使用的是默认配置。

同时也不能保证dataSourceName是唯一的。例如,如果两个 c3p0 数据源共享相同的命名配置,并且您没有以编程方式设置dataSourceName,则两个数据源将共享配置的名称。要获取具有特定 dataSourceName的所有数据源,请使用pooledDataSourcesByName( ... )。如果您已确保您的数据源的名称是唯一的(如果您打算使用 C3P0Registry来查找您的数据源,您通常会希望这样做),您可以使用便捷方法pooledDataSourceByName( ... ),它将返回您的数据源直接,或如果没有具有该名称的数据源可用,则为null 。如果您使用pooledDataSourceByName( ... ) 并且多个 DataSource 共享所提供的名称,则它将返回哪一个是未定义的。

在 c3p0 PooledDataSources 之后清理

在 c3p0 创建的 DataSources 之后清理的简单方法是使用类DataSources定义的静态 destroy 方法。只有 PooledDataSource需要清理,但 DataSources.destroy( … ) 如果在未池化或非 c3p0 数据源上调用则不会有任何危害。

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()方法,您可以在知道已完成数据源时调用该方法。因此,您可以将 c3p0 派生的 DataSource 转换为PooledDataSource并关闭它:

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 );
}
      

ComboPooledDataSourcePooledDataSource的一个实例,可以通过它的close()方法直接PooledDataSource实现java.lang.AutoCloseable,因此它们可以由 Java 7+ try-with-resources块管理。

未被引用的PooledDataSource 实例在其finalize()方法中的垃圾收集之前 未被客户端close()掉自己 。与往常一样,finalization 应被视为一种兜底,而不是一种迅速或可靠的资源清理方法。

高级:构建您自己的 PoolBackedDataSource

大多数程序员没有理由这样做,但是您可以通过实例化和配置未合并的 DriverManagerDataSource、实例化 WrapperConnectionPoolDataSource 并将未合并的 DataSource 设置为其nestedDataSource属性,然后使用它来逐步构建 PooledDataSource设置新 PoolBackedDataSource的connectionPoolDataSource属性。

如果您的驱动程序提供了 ConnectionPoolDataSource 的实现,并且您希望 c3p0 使用它,那么这一系列事件将非常有趣。您可以创建一个PoolBackedDataSource 并设置其connectionPoolDataSource属性,而不是使用 c3p0 的 WrapperConnectionPoolDataSource ConnectionPoolDataSource的第三方实现不支持语句池、 ConnectionCustomizers和许多特定于 c3p0 的属性。(第三方DataSource实现可以替代 c3p0 的 DriverManagerDataSource而不会显着损失功能。)

高级:原始连接和语句操作

注意:从 c3p0-0.9.5 开始,c3p0 支持标准的 JDBC4 unwrap ()方法来查看代理。请注意,如果您使用unwrap()方法,c3p0 无法清除您可能从原始连接或语句生成的任何语句结果集对象。用户必须注意直接清理这些对象。此外,用户应注意不要以某种方式修改底层Connection,这会使它们不再与其他Connection互换,因为它们必须保持适合池化。

JDBC 驱动程序有时会在连接和语句实现上定义特定于供应商的非标准 API。C3P0 将这些对象包装在代理后面,因此您不能将 C3P0 返回的连接或语句转换为特定于供应商的实现类。C3P0 不提供任何直接访问原始连接和语句的方法,因为 C3P0 需要跟踪创建的语句和结果集以防止资源泄漏和池损坏。

C3P0 确实提供了一个 API,允许您在底层连接上以反射方式调用非标准方法。要使用它,首先将返回的 Connection 转换为 C3P0ProxyConnection。然后调用方法rawConnectionOperation,为您希望调用的非标准方法提供java.lang.reflect.Method对象作为参数。您提供的方法将在您提供的第二个参数(静态方法为空)的目标上调用,并使用您在该函数的第三个参数中提供的参数。对于目标和任何方法参数,您可以提供特殊标记C3P0ProxyConnection.RAW_CONNECTION,在调用 方法之前将替换为底层供应商特定的连接对象。

C3P0ProxyStatement提供了一个完全类似的 API。

原始操作返回的任何语句(包括 Prepared 和 CallableStatements)和结果集都将由 c3p0 管理,并将在父代理连接的close()上正确清理。用户必须注意清理供应商特定方法返回的任何非标准资源。

下面是使用 Oracle 特定 API 调用原始连接上的静态方法的示例:

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 的方法的特殊支持。见 附录F

配置

介绍

虽然 c3p0不需要太多配置,但它非常容易调整。大多数有趣的旋钮和转盘都表示为 JavaBean 属性。遵循 JavaBean 约定,我们注意到如果一个 Object 有一个名为fooT类型的属性,它将有看起来如下的方法

public T getFoo();
public void setFoo(T foo);

…或两者兼而有之,具体取决于该属性是只读、只写还是可读写。

有几种方法可以修改 c3p0 属性:您可以直接更改与代码中特定数据源关联的属性值,或者您可以在外部配置 c3p0…

配置文件通常在应用程序类路径顶层的标准名称( c3p0.propertiesc3p0-config.xml)下查找,但如果系统属性com .mchange.v2.c3p0.cfg.xml已设置。

DataSources 通常在使用前配置,或者在构建期间或构建之后立即配置。但是,c3p0 确实支持中途修改属性。

如果您通过实例化ComboPooledDataSource 获得 DataSource ,则在尝试调用getConnection()之前,只需调用该类提供的适当设置方法来配置它。请参见上面的示例。

如果您通过使用实用程序类com.mchange.v2.c3p0.DataSources的工厂方法获得数据源,并希望使用非默认配置,您可以提供一个属性名称映射(以小写字母开头)以属性值(作为字符串或“盒装”Java 原语,如 Integer 或 Boolean)。

所有可调整的属性都记录在附录 A中以供参考。大多数 c3p0 配置主题在下面详细讨论。

基本池配置

c3p0 连接池很容易通过以下基本参数进行配置:

initialPoolSizeminPoolSizemaxPoolSize 定义将被合并的连接数。请确保 minPoolSize <= maxPoolSize。不合理的initialPoolSize值将被忽略,取而代之的是minPoolSize

在minPoolSizemaxPoolSize 之间的范围内,池中的连接数根据使用模式而变化。每当用户请求连接时,连接数就会增加,没有连接可用,并且池管理的连接数尚未达到maxPoolSize

由于 Connection 的获取速度非常慢,因此在负载增加时,急切地、分批地增加 Connection 的数量几乎总是有用的,而不是强制每个客户端等待新的 Connection 来激发单次获取。acquireIncrement确定当池用完连接数时 c3p0 池将尝试获取多少连接数。(无论acquireIncrement如何,池都不会允许超过maxPoolSize。)

每当池测试一个连接并发现它被破坏时,池中的连接数就会减少(请参阅 下面的配置连接测试),或者当一个连接在闲置一段时间后被池过期,或者太久了旧(请参阅管理池大小和连接年龄。)

管理池大小和连接年龄

不同的应用程序在性能、占用空间和可靠性之间的权衡方面有不同的需求。C3P0 提供了多种选项来控制在负载下变大的池恢复到minPoolSize的速度,以及是否应主动替换池中的“旧”连接以保持其可靠性。

默认情况下,池永远不会过期连接。如果您希望连接随时间过期以保持“新鲜度”,请设置maxIdleTime和/或maxConnectionAgemaxIdleTime定义在从池中剔除之前应该允许 Connection 闲置多少秒。maxConnectionAge 强制池剔除过去从数据库获取的超过设定秒数的所有连接。

maxIdleTimeExcessConnections是关于在池未负载时最小化 c3p0 池持有的连接数。默认情况下,c3p0 池会在负载下增长,但只有在连接未通过连接测试或通过上述参数过期时才会缩小。一些用户希望他们的池在使用量激增后快速释放不必要的连接,从而迫使池大小变大。您可以通过将maxIdleTimeExcessConnections设置为比 maxIdleTime短得多的值来实现此目的,如果连接闲置时间超过短时间,则强制释放超出您设置的最小大小的连接。

关于所有这些超时参数的一些一般性建议: 放慢速度!Connection pooling的要点就是承担只获取一次Connection的代价,然后可以多次重用这个Connection。大多数数据库支持一次保持打开数小时的连接。无需每隔几秒或几分钟就浏览所有连接。将maxConnectionAgemaxIdleTime设置为 1800(30 分钟)是非常激进的。对于大多数数据库,几个小时可能更合适。您可以通过测试而不是折腾它们来确保您的 Connections 的可靠性。(请参阅 配置连接测试。)通常应将这些参数设置为几分钟或更短时间的唯一参数是最大空闲时间超额连接数

配置连接测试

c3p0 可以配置为测试它以各种方式汇集的连接,以最大限度地减少您的应用程序看到损坏或“陈旧”连接的可能性。池连接可能因各种原因而变坏——一些 JDBC 驱动程序故意“超时”持久的数据库连接;后端数据库或网络有时会“搁浅”合并连接;由于资源泄漏、驱动程序错误或其他原因,随着时间的推移和使用,连接可能会简单地损坏。

c3p0 通过以下配置参数为用户提供了很大的连接测试灵活性:

idleConnectionTestPeriodtestConnectionOnCheckouttestConnectionOnCheckin控制何时测试连接。 automaticTestTableconnectionTesterClassNamepreferredTestQuery控制它们的测试方式 。

配置Connection测试时,首先要尽量减少每次测试的开销。如果您使用的是 JDBC 驱动程序,那么您肯定支持新的(ish)jdbc4 API — 如果您使用的是 c3p0-0.9.5 或更高版本!— 让您的司机为您处理。jdbc4 Connections 包括一个名为 isValid()的方法,该方法应作为快速、可靠的连接测试来实现。默认情况下,c3p0 将使用该方法(如果存在)。

但是,如果您的驱动程序不支持这个新的 API,c3p0 的默认行为是通过在连接的关联DatabaseMetaData 对象上调用getTables()方法来测试连接。这样做的优点是非常健壮并且可以与任何数据库一起使用,而不管数据库模式如何。但是,调用DatabaseMetaData.getTables()通常比简单的数据库查询慢得多,并且使用此测试可能会显着损害池的性能。````

在 JDBC 3 驱动程序(或 0.9.5 之前的 c3p0 版本)下加速连接测试的最简单方法是使用preferredTestQuery 参数定义测试查询。但是要小心。如果在初始化 DataSource 之前数据库中不存在查询目标表,则设置preferredTestQuery将导致错误,因为连接测试失败。根据您的数据库和 JDBC 驱动程序,与表无关的查询(如SELECT 1)可能(或可能不)足以验证连接。如果与表无关的查询不够,而不是preferredTestQuery,您可以设置参数`automaticTestTable```````. 使用您提供的名称,c3p0 将创建一个空表,并对其进行简单查询以测试数据库。

测试 Connections 的最可靠时间是在结帐时。但从客户端性能的角度来看,这也是成本最高的选择。大多数应用程序应该结合使用idleConnectionTestPeriodtestConnectionOnCheckin来相当可靠地工作 。空闲测试和签入测试都是异步执行的,这可以带来更好的性能,无论是感知的还是实际的。

对于某些应用程序,高性能比偶尔出现数据库异常的风险更重要。在其默认配置中,c3p0 根本不进行连接测试。设置相当长的 idleConnectionTestPeriod并且根本不对签出和签入进行测试是一种出色的高性能方法。

当没有可用的preferredTestQueryautomaticTestTable时 ,可以自定义 c3p0 的DefaultConnectionTester测试方式。请参阅配置 DefaultConnectionTester.isValidTimeout配置 DefaultConnectionTester.QuerylessTestRunner

高级用户可以通过实现 ConnectionTester并将类的完全限定名称提供为connectionTesterClassName来定义他们希望的任何类型的连接测试。如果您希望您的自定义 ConnectionTesters 遵守并支持preferredTestQueryautomaticTestTable参数,请实施 UnifiedConnectionTester,最方便的方法是扩展 AbstractConnectionTester。有关详细信息,请参阅api 文档

如果您知道要使用 jdbc4 Connection.isValid()方法,但要设置超时,请考虑编写IsValidConnectionTester的简单扩展。

package com.mchange.v2.c3p0.example;

import com.mchange.v2.c3p0.util.IsValidOnlyConnectionTester;

public final class IsValidOnlyConnectionTester30 extends IsValidOnlyConnectionTester
{
    protected int getIsValidTimeout() { return 30; }
}
      

这些写起来真的很简单。

关于连接测试的简单建议如果你不知道该怎么做,试试这个:

  1. 如果您知道您的驱动程序支持 JDBC 4 Connection.isValid(...)方法并且您使用的是 c3p0-0.9.5 或更高版本,请不要设置preferredTestQuery。如果您的驱动程序不支持此方法(或者如果您不确定),请尝试为您的preferredTestQuery设置**SELECT 1**,如果您正在运行 MySQL 或 Postgres。对于其他数据库,请在此处寻找 建议。保留automatedTestTable不定义。

  2. 首先将testConnectionOnCheckout设置为true并让您的应用程序正确稳定地运行。如果您对应用程序的性能感到满意,*您可以到此为止!*这是最简单、最可靠的连接测试形式,但它确实具有客户端可见的性能成本。

  3. 如果您想通过消除客户端代码路径中的连接测试来提高性能:

    1. testConnectionOnCheckout设置为false
    2. testConnectionOnCheckin设置为true
    3. idleConnectionTestPeriod设置为30,启动您的应用程序并观察。这是一个非常强大的设置,所有连接都将在检入时进行测试,此后在池中每 30 秒测试一次。您的应用程序应该很少遇到断开或过时的连接,并且池应该从数据库关闭中恢复并快速重新启动。但是所有这些连接测试都会产生一些开销。
    4. 如果数据库很少重新启动,那么快速恢复不是问题,请考虑将idleConnectionTestPeriod的测试频率降低到,比如300,并查看客户端是否受到陈旧或损坏连接的困扰。如果不是,请坚持使用300或尝试更大的数字。考虑将testConnectionOnCheckin设置回 false 以避免对签入进行不必要的测试。或者,如果您的应用程序确实遇到了错误的连接,请考虑减少idleConnectionTestPeriod 并将testConnectionOnCheckin设置回true. 这些参数没有正确或不正确的值:您在决定测试频率时以可靠性换取开销。确切的数字并不那么重要。通常很容易找到性能良好的配置。在这里花时间追求“最佳”值几乎不值得。

那么,什么时候应该坚持简单可靠(上面的第 2 步),什么时候值得为获得更好的性能而努力(第 3 步)?

通常,这取决于客户检出后通常使用 Connections 执行的工作量。如果客户通常进行复杂的查询和/或执行多项操作,则每次结帐时增加一次快速测试的额外成本不会对性能产生太大影响。但是,如果您的应用程序通常检查一个连接并使用它执行一个简单的查询,那么投入额外的测试确实会减慢速度。

这在理论上很好,但通常人们并不真正了解客户的平均工作量。最好的做法通常是尝试第 3 步,看看它是否有帮助(无论您如何衡量性能),看看它是否有害(您的应用程序是否因连接中断而烦恼?它是否从数据库重启中恢复得足够好?),然后再决定。你总是可以回到简单、缓慢和健壮的状态。只需将testConnectionOnCheckout设置为true,将testConnectionOnCheckin设置为false,并将idleConnectionTestPeriod设置为0

但是,请始终确保您的测试本身是高性能的,因为您的 JDBC 驱动程序支持Connection.isValid(...)或因为您设置了高效的 p referredTestQuery !!!

配置语句池

c3p0 实现了 JDBC 规范定义的透明 PreparedStatement 池。在某些情况下,语句池可以显着提高应用程序性能。在其他情况下,语句池的开销可能会稍微损害性能。语句池是否有帮助以及有多大帮助取决于准备语句时数据库对查询进行了多少解析、规划和优化。数据库(和 JDBC 驱动程序)在这方面差异很大。最好在使用和不使用语句池的情况下对您的应用程序进行基准测试,看看它是否有帮助以及有多大帮助。

您可以通过以下配置参数在 c3p0 中配置语句池:

maxStatements是 JDBC 用于控制语句池的标准参数。maxStatements定义数据源将缓存的PreparedStatements总数。当达到此限制时,池将销毁最近最少使用的 PreparedStatement。这听起来很简单,但实际上是一种奇怪的方法,因为缓存的语句在概念上属于各个连接;它们不是全球资源。要计算出不会“扰乱”缓存语句的maxStatements的大小,您需要考虑应用程序中经常使用的 PreparedStatements 的数量,并将其乘以池中您期望的连接数(繁忙应用程序中的maxPoolSize ) .

maxStatementsPerConnection是一个非标准配置参数,在概念上更有意义。它定义了每个池连接允许拥有多少条语句。您可以将其设置为比您的应用程序经常使用的PreparedStatements数量多一点 ,以避免搅动。

如果这些参数中的任何一个大于零,将启用语句池。如果两个参数都大于零,则将强制执行两个限制。如果只有一个大于零,将启用语句池,但只会强制执行一个限制。

如果statementCacheNumDeferredCloseThreads大于零,则语句池将延迟物理关闭缓存的语句,直到其父连接未被任何客户端使用或在内部(例如在测试中)被池本身使用。对于某些 JDBC 驱动程序(尤其是 Oracle),如果父连接正在使用,则会尝试关闭语句冻结。此参数默认为 0。如果您观察到与连接关闭任务相关的“明显死锁”,请将其设置为正值。几乎总是,该值应该是一个:如果您需要多个专用于 Statement 销毁的 Thread,您可能应该将maxStatementsmaxStatementsPerConnection设置为更高的值,这样您就不会如此快速地翻阅缓存的 Statements。

配置数据库中断恢复

c3p0 数据源被设计(并默认配置)以从临时数据库中断中恢复,例如在数据库重新启动或网络连接短暂丢失期间发生的中断。您可以通过以下可配置属性影响 c3p0 处理获取连接错误的方式:

当 c3p0 数据源尝试获取连接失败时,它将重试acquireRetryAttempts次, 每次尝试之间有acquireRetryDelay的延迟。如果所有尝试都失败,任何等待来自 DataSource 的连接的客户端都会看到异常,表明无法获取连接。请注意,在整轮尝试失败之前,客户端看不到任何异常,这可能是在初始连接尝试之后的某个时间。如果acquireRetryAttempts 设置为 0,c3p0 将无限期地尝试获取新的连接,并且对 getConnection()的调用可能会无限期地阻塞以等待成功获取。

一旦整轮收购尝试失败,有两种可能的策略。默认情况下,c3p0 数据源将保持活动状态,并将再次尝试获取连接以响应未来的连接请求。如果将breakAfterAcquireFailure设置 为true,则 DataSource 将在一轮失败的连接尝试后认为自己已损坏,并且以后的客户端请求将立即失败。

请注意,如果发生数据库重新启动,则池可能包含以前获取但现在过时的连接。默认情况下,这些陈旧的连接只会在应用程序尝试使用它们并看到异常时才被延迟检测和清除。设置 maxIdleTimemaxConnectionAge可以帮助加快更换损坏的连接。(请参阅管理 ConnectionAge。)如果您希望完全避免应用程序异常,则必须采用一种连接测试策略,该策略可能会在将过时的连接交付给客户端之前检测到它们。(请参阅“配置连接测试”。)即使使用活动连接测试(testConnectionOnCheckout设置为true,或 testConnectionOnCheckin和一个简短的idleConnectionTestPeriod),您的应用程序可能会在数据库重新启动时偶尔出现异常,例如,如果重新启动发生在与数据库的连接已经被检出之后。

使用 Connection Customizer 管理连接生命周期

应用程序经常希望在获取连接后立即以某种标准的、可重用的方式设置连接。这方面的示例包括使用特定于供应商的 API 或非标准 SQL 语句执行设置字符编码或日期和时间相关行为。有时覆盖标准连接属性的默认值很有用,例如transactionIsolationholdabilityreadOnly. c3p0 提供了一个您可以实现的“挂钩”接口,它使您有机会在连接从数据库中检出之后、在检出时交给客户之前、在返回到数据库之前立即修改或跟踪连接。登记入住时的泳池,以及泳池最终销毁之前的泳池。传递给 ConnectionCustomizers 的连接是原始的物理连接,可以访问所有特定于供应商的 API。请参阅ConnectionCustomizer的 API 文档。

要安装ConnectionCustomizer,只需实现接口,让 c3p0 的 ClassLoader 可以访问您的类,并设置以下配置参数:

ConnectionCustomizers 必须是具有公共无参数构造函数的不可变类。他们不应该存储任何状态。对于希望使用 ConnectionCustomizers 跟踪单个 DataSource 的行为的(罕见)应用程序,每个生命周期方法都接受一个特定于 DataSource 的“identityToken”,它对每个 PooledDataSource 都是唯一的。ConnectionCustomizers 可以通过用户定义的配置扩展进行配置。

下面是一个示例ConnectionCustomizer。不需要覆盖所有四种ConnectionCustomizer方法的实现可以扩展 AbstractConnectionCustomizer 以继承所有方法的无操作实现。

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 + "]"); }
}
      

有关使用用户定义的配置属性的示例ConnectionCustomizer,请参见下文

配置未解决的事务处理

签入池中的连接不能有任何与之关联的未解决的事务性工作。如果用户在连接上将autoCommit设置为false,并且 c3p0 无法保证没有未决的事务工作,则 c3p0 必须在签入时使用rollback()commit() (当用户调用close()时)。JDBC 规范(不可原谅)对未解决的工作是否应在连接关闭时提交或回滚的问题保持沉默。默认情况下,c3p0 在用户调用close()时回滚未解决的事务工作。

您可以通过以下配置属性调整此行为:

如果您希望 c3p0 允许未解决的事务性工作在签入时提交,请将autoCommitOnClose设置 为 true。如果您希望 c3p0 将事务管理留给您,既不提交也不回滚(也不修改 Connection autoCommit的状态),您可以将forceIgnoreUnresolvedTransactions设置为 true。强烈建议不要设置 forceIgnoreUnresolvedTransactions,因为如果客户端在 close() 之前不小心提交或回滚自己,或者没有始终如一地设置 Connection autoCommit,就会发生奇怪的不可重现的行为和数据库锁定。

配置调试和解决损坏的客户端应用程序

有时,客户端应用程序对关闭()检查它们检查的所有连接草率。最终,池增长到maxPoolSize,然后由于这些不良客户端而耗尽连接。

解决此问题的正确方法是修复客户端应用程序。c3p0可以帮助您进行调试,让您知道连接在何处检出,但偶尔不会检入。在极少数和不幸的情况下,客户端应用程序的开发已关闭,即使它有错误,您也无法修复它。c3p0 可以帮助您解决损坏的应用程序,防止它耗尽池。

以下参数可以帮助您调试或解决损坏的客户端应用程序。

unreturnedConnectionTimeout定义连接可以保持签出的时间限制(以秒为单位)。如果设置为 nozero 值,未返回的、超过此限制的签出连接将被立即销毁,然后在池中替换。显然,您必须注意将此参数设置为足够大的值,以便对签出的连接进行的所有预期操作都有时间完成。您可以使用此参数仅解决无法关闭 () 连接的不可靠客户端应用程序。

修复比解决方法要好得多。如果除了 设置unreturnedConnectionTimeout之外,``还将 debugUnreturnedConnectionStackTraces设置为true,那么每次签出连接时都会捕获堆栈跟踪。每当未返回的 Connection 超时时,将打印该堆栈跟踪,以显示未及时签入的 Connection 签出的位置。debugUnreturnedConnectionStackTraces 旨在仅用于调试,因为捕获堆栈跟踪会减慢连接签出速度。

配置以避免在热重新部署客户端时发生内存泄漏

c3p0 生成各种线程(辅助线程java.util.Timer线程),并懒惰地响应 PooledDataSource 遇到的第一个客户端请求。默认情况下,由 c3p0 生成的线程从这个首次调用的线程继承java.security.AccessControlContextcontextClassLoader属性。如果该 Thread 来自可能需要热卸载的客户端,则对这些对象的引用可能会阻止未部署的应用程序(通常分区到ClassLoader)被垃圾收集。(例如,参见 Tomcat memory leaks on redeployment 的描述。)

c3p0 提供了两个可以帮助解决这个问题的配置参数:

contextClassLoaderSource应设置为callerlibrarynone之一。默认值(产生上述默认行为)是caller。将此设置为 以使用 c3p0 的类加载器,这样就不会维护对可能需要重新部署的客户端的引用。

privilegeSpawnedThreads`是一个布尔值,默认情况下为`false`。将其设置为`true` 以便 c3p0 的线程使用 c3p0 库的`AccessControlContext`,而不是 可能与客户端应用程序关联并防止其垃圾收集 的`AccessControlContext 。

其他数据源配置

有关以下配置属性的信息, 请参阅附录 A :

numHelperThreadsmaxAdministrativeTaskTime有助于配置数据源线程池的行为。默认情况下,每个 DataSource 只有三个关联的辅助线程。如果性能似乎在重负载下拖累,或者如果您通过 JMX 或直接检查PooledDataSource观察到“待处理任务”的数量通常大于零,请尝试增加numHelperThreadsmaxAdministrativeTaskTime对于遇到无限期挂起的任务和“明显死锁”消息的用户可能很有用。(更多信息请参见附录 A。)

通常检入是异步执行的,这样客户端就不会遇到检入连接测试和ConnectionCustomizer.onCheckIn(...)中指定的操作的开销。但是,异步检入会增加线程池拥塞。在负载如此之大以至于扩展numHelperThreads以减少拥塞是不切实际的情况下,forceSynchronousCheckins 将导致客户端线程执行检入操作,增加线程池的负载并排除由于线程池拥塞而终止检入的任何延迟。只要您既不在签入时执行连接测试(请参阅testConnectionOnCheckin),也不执行数据库操作或其他缓慢的工作ConnectionCustomizer.onCheckIn(...),此设置可能会提高性能。但是,如果在签入时测试连接*,*或执行自定义工作,则设置forceSynchronousCheckins将导致客户端在调用Connection.close()时遇到与该工作相关的延迟。

checkoutTimeout限制客户端等待连接的时间,如果所有连接都已签出并且不能立即提供一个。usesTraditionalReflectiveProxies几乎没有实际用途,现在已正式弃用。它允许您使用旧的、现在已被取代的 C3P0 生成代理对象的实现。(C3P0 过去使用反射的动态代理。现在,为了增强性能,它使用代码生成的非反射实现。)如果c3p0数据源将被检索为未在本地安装 c3p0 的客户端从 JNDI 数据源引用。

通过 JMX 配置和管理 c3p0

如果 JMX 库和 JMX MBeanServer 在您的环境中可用(它们包含在 JDK 1.5 及更高版本中),您可以通过 JMX 管理工具(例如 jconsole,与 jdk 1.5 捆绑在一起)检查和配置您的 c3p0 数据源。您会发现 c3p0 在域com.mchange.v2.c3p0下注册了 MBean ,其中一个包含有关整个库的统计信息(称为C3P0Registry ),以及您部署的每个PooledDataSource的 MBean 。您可以查看和修改数据源的配置属性,跟踪连接、语句和线程池的活动,并通过PooledDataSource MBean 重置池和数据源。(您可能希望查看 PooledDataSource的 API 文档用于可用操作的文档。)

配置 JMX 名称

您的应用程序中的每个PooledDataSource都可能在其ObjectName中嵌入了以下属性:

  • type
  • identityToken
  • type

类型将始终为PooledDataSourceidentityToken是与每个 c3p0 数据源关联的唯一字符串。该名称将是属性dataSourceName的值,您可以自己设置该名称以确保在应用程序重新启动时可以识别语义上等效的数据源。如果您没有设置dataSourceName,则 name 属性可能根本没有定义,或者它可能采用一些默认值。

例如,以下可能是dataSourceNameintergalactoApp的 c3p0 数据源的字符串格式的完整 JMX ObjectName :

com.mchange.v2.c3p0:type=PooledDataSource,identityToken=2rvy139515ecj0rkwntk|16adc251,name=intergalactoApp

c3p0 更喜欢在 JMX ObjectNames 中包含身份标记,以确保每个 ObjectName 都是唯一的。如果可以,请坚持使用 c3p0 的默认行为。但如果您真的需要,您可以配置 c3p0 以从 ObjectNames 中排除identityToken属性,这样您的 PooledDataSources 就有可预测的、可重现的名称。在c3p0.propertiesHOCON config中将以下设置为系统属性:

com.mchange.v2.c3p0.management.ExcludeIdentityToken=true

这将导致名称缺少长身份令牌,名称如

com.mchange.v2.c3p0:type=PooledDataSource,name=intergalactoApp

如果从 JMX 名称中排除身份标记,则必须确保每个 PooledDataSource 始终具有唯一的dataSourceName值! 否则,JMX 只能访问具有相同名称的 PooledDataSources 之一,而哪一个将是未定义的。如果您要从同一个命名配置初始化多个数据源,那么从 JMX 名称中排除身份标记尤其危险。默认情况下,dataSourceName采用配置名称的值。 在构建具有命名配置的 PooledDataSouce 之后,请确保在构建具有相同命名配置的第二个数据源之前将dataSourceName更新为某个新的唯一值。

单例C3P0Registry也由 MBean 表示。它可能在其 JMX ObjectName中嵌入了以下属性:

  • type
  • name

name 属性的值由以下属性确定,该属性可以在c3p0.propertiesHOCON config中设置为系统属性。

com.mchange.v2.c3p0.management.RegistryName=CoolC3P0注册表

使用上面显示的 RegistryName,字符串格式的完整 JMX ObjectName 将是

com.mchange.v2.c3p0:type=C3P0Registry,name=CoolC3P0Registry

如果您没有显式设置 RegistryName,则不会使用默认值,也不会嵌入名称属性。字符串格式的完整 JMX ObjectName 将是

com.mchange.v2.c3p0:type=C3P0Registry

禁用 JMX 支持

如果您不希望 c3p0 在您的 JMX 环境中注册 MBean,您可以完全抑制 JMX 支持。在c3p0.propertiesHOCON config中将以下设置为系统属性:

com.mchange.v2.c3p0.management.ManagementCoordinator=com.mchange.v2.c3p0.management.NullManagementCoordinator

配置日志记录

c3p0 使用类似于 jakarta commons-logging 的自定义日志记录库。日志消息可以定向到流行的slf4j(及其logback 后端)、古老的 log4j 库、更新的 log4j2 库、jdk1.4 引入的标准日志记录工具或 System.err。几乎所有配置都应在您首选的日志记录库级别完成。有很少的配置选项专门针对 c3p0 的日志记录,通常默认值就可以了。与日志相关的参数可以放在你的c3p0.properties文件中,在 HOCON 配置文件中,在一个名为mchange-log.properties的文件中在你的类路径的顶层,或者它们可以被定义为系统属性。(下面定义的日志记录属性可能未在c3p0-config.xml中定义!)请参阅下面的

c3p0 的日志记录行为受某些构建时选项的影响。如果 build-option c3p0.debug设置为false,所有低于 INFO 的日志记录级别的消息都将被抑制。构建选项c3p0.trace控制低于 INFO 级别的 c3p0 报告的细粒度。目前,分布式 c3p0 二进制文件在调试设置为true并将跟踪设置为其最大级别10的情况下进行编译。但是二进制文件最终可能会在调试设置为false的情况下分发. (目前,日志级别检查的性能影响似乎很小,编译所有消息是最灵活的,让你的日志库控制哪些被发出。)当 c3p0 启动时,它发出构建 -调试和跟踪的时间值,以及版本和构建时间。

  • com.mchange.v2.log.MLog

  • com.mchange.v2.log.MLog.useRedirectableLoggers

    使用com.mchange.v2.log.MLog中的 API,可以在运行时更改库 c3p0 输出日志的内容,或者将中游切换到基于标准错误的回退记录器。但是,为了使其有用,已经根据原始配置构建的记录器需要对更改敏感。将此值设置为true 将导致 c3p0 使用性能稍差的记录器,这些记录器可以在运行时在库之间重定向。默认情况下此设置为false

  • com.mchange.v2.log.jdk14logging.suppressStackWalk

  • com.mchange.v2.log.NameTransformer

  • com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL

命名配置

您可以定义命名配置,以扩充和覆盖您定义的默认配置。当您实例化 c3p0 PooledDataSource时,无论是通过 ComboPooledDataSource 构造函数还是通过 [DataSources](https://www.mchange.com/projects/c3p0/apidocs/com/mchange/v2/c3p0/DataSources.html#pooledDataSource(javax.sql.DataSource, java.lang.String)) 工厂类,您都可以提供一个配置名称。例如,使用 ComboPooledDataSource

ComboPooledDataSource cpds = new ComboPooledDataSource("intergalactoApp");

或者使用 DataSources工厂类:

DataSource ds_pooled = DataSources.pooledDataSource( ds_unpooled, "intergalactoApp" );

定义命名配置…

属性样式的配置文件中…

# 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 配置文件中…

c3p0 {
  maxPoolSize=30
  minPoolSize=10

  named-configs {
    intergalactoApp {
      maxPoolSize=1000
      minPoolSize=100
      numHelperThreads=50
    }
    littleTeenyApp {
      maxPoolSize=5
      minPoolSize=2
    }
  }
}

XML 配置文件中…

<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>

每用户配置

您可以定义仅适用于为特定用户验证的连接池的默认或命名配置的覆盖。并非所有配置参数都支持按用户覆盖。详见附录A。

要定义每个用户的配置…

属性样式的配置文件中…

# 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 配置文件中…

c3p0 {
  maxPoolSize=30
  minPoolSize=10

  user-overrides {
    steve {
      maxPoolSize=15
      minPoolSize=5
    }
    ramona {
      maxPoolSize=50
      minPoolSize=20
    }
  }
}

XML 配置文件中…

<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的行为。用户配置存储为包含字符串键和值的映射,存储在以下配置参数下:

可以像任何其他配置参数一样以编程方式设置 扩展Map。但是,特别支持 在配置文件中为扩展映射定义键和值。

属性样式的配置文件中…

c3p0.extensions.initSql=SET SCHEMA 'foo'
c3p0.extensions.timezone=PDT
...
      

HOCON 配置文件中…

c3p0 {
  extensions {
     initSql=SET SCHEMA 'foo'
     timezone=PDT
  }
}

XML 配置文件中…

<c3p0-config>
  <default-config>
    <extensions>
      <property name="initSql">SET SCHEMA 'foo'</property>
      <property name="timezone">PDT</property>
    </extensions>
  </default-config>
</c3p0-config>

要查找为PooledDataSource定义的扩展,您必须有权访问其 identityToken ,它作为所有ConnectionCustomizer方法的参数提供 。给定一个identityToken,您可以使用方法 C3P0Registry.extensionsForToken(...)来访问扩展Map

由于扩展主要设计用于ConnectionCustomizer实现中,因此AbstractConnectionCustomizer 类还定义了一个受保护的 extensionsForToken(…)方法以方便使用。

下面是一个使用用户定义的配置扩展的ConnectionCustomizer实现示例。它定义了一个initSql扩展,其值应该是一个包含 SQL 的字符串,当从池中检出 连接时应该执行该 SQL :

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(); }
	}
    }
}
      

注意:如果您只需要initSql ,则 无需实现自己的ConnectionCustomizer。这个例子加上一些额外的 TRACE 级日志记录,在库中实现为 com.mchange.v2.c3p0.example.InitSqlConnectionCustomizer

混合命名的、每个用户的和用户定义的配置扩展

命名配置、每个用户覆盖和用户定义的配置扩展可以很容易地混合使用。

属性样式的配置文件中…

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 配置文件中…

c3p0 {
  maxPoolSize=30
  extensions {
    initSql=SET SCHEMA 'default'
  }
  named-configs {
    intergalactoApp {
      maxPoolSize=1000
      user-overrides {
        steve {
          maxPoolSize=20
        }
      }
      extensions {
        initSql=SET SCHEMA 'intergalacto'
      }
    }
  }
}

XML 配置文件中…

<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>

表现

增强性能是连接和语句池的目的,也是 c3p0 库的主要目标。对于大多数应用程序,连接池将提供显着的性能提升,尤其是当您为每个客户端访问获取一个非池化连接时。如果您让一个共享的 Connection 为多个客户端提供服务以避免 Connection 获取开销,那么当您的 Connection 处于并发负载下时,您可能会遇到性能问题和事务管理问题;连接池将使您能够以很少或没有成本切换到一个每个客户端一个连接的模型。如果您正在编写 Enterprise Java Bean,您可能会想要获取一次连接,并且在 bean 即将被销毁或钝化之前不返回它。但这可能会消耗大量资源,因为休眠的池 bean 不必要地持有连接的网络和数据库资源。连接池允许 bean 在使用时只“拥有”一个连接。

但是,c3p0 也有性能成本。为了在父资源返回到池时实现未关闭的ResultSetsStatements的自动清理,所有客户端可见的ConnectionsResultSetsStatements 实际上是对底层未池化 DataSource 或“传统”JDBC 驱动程序提供的对象的包装。因此,所有 JDBC 调用都有一些额外的开销。

一些注意力已经放在最小化 c3p0 的“包装器”开销上。在我的环境中,包装器开销从连接获取成本的百分之几到千分之一不等,因此除非您快速连续地进行许多 JDBC 调用,否则性能和资源利用效率将获得净收益。值得注意的是,与 ResultSet 操作相关的开销(可能会遍历包含数千条记录的表)似乎可以忽略不计。

已知缺点

  • 连接和语句在每次身份验证的基础上汇集在一起。因此,如果使用一个池支持的数据源来为 [ user =alice, password =secret1] 和 [ user =bob, password =secret2] 获取连接,将有两个不同的池,并且数据源可能在最坏的情况下管理两倍于maxPoolSize属性 指定的连接数 。

    这一事实是 DataSource 规范定义(允许通过多个用户身份验证获取连接)以及单个池中所有连接在功能上相同的要求的自然结果。这个“问题”不会改变或修复。在这里注明只是为了让您了解发生了什么。

  • Statement pooling 的开销太大。对于不对 PreparedStatements 执行大量预处理的驱动程序,池开销超过任何节省。因此默认情况下语句池是关闭的。如果您的驱动程序确实预处理PreparedStatements,特别是如果它通过 IPC 和 RDBMS 这样做,您可能会通过打开语句池看到显着的性能提升。(通过将配置属性maxStatementsmaxStatementsPerConnection 设置为大于零的值来执行此操作。)。

反馈和支持

请向 < swaldman@mchange.com > 提供所有反馈!另外,请随时加入c3p0-users邮件列表并提出问题。在http://sourceforge.net/projects/c3p0/注册

感谢您使用 c3p0!!!

附录 A:配置属性

c3p0 配置属性可以分为JavaBeans-style PropertiesOther Properties

JavaBeans 风格的属性

以下属性可以直接在代码中设置为 JavaBeans 属性,通过系统属性c3p0.properties 文件(在属性名称前加上c3p0.),在HOCON(类型安全配置)文件中,或在c3p0-config 中。 xml文件。请参阅上面的 配置部分。单击属性名称以获取完整说明。

  • acquireIncrement

    默认值:3. 确定当池耗尽时 c3p0 一次将尝试获取多少个连接。[参见“基本池配置” ]

  • acquireRetryAttempts

    默认值:30. 定义 c3p0 在放弃之前尝试从数据库获取新连接的次数。如果此值小于或等于零,c3p0 将继续尝试无限期地获取连接。[参见“配置数据库中断恢复” ]

  • acquireRetryDelay

    默认值:1000毫秒,c3p0 将在获取尝试之间等待的时间。[参见“配置数据库中断恢复” ]

  • autoCommitOnClose

    默认值:假. JDBC 规范对于在连接关闭时未解决的、挂起的事务应该发生什么应该保持沉默是不可原谅的。C3P0 的默认策略是回滚任何未提交的、挂起的工作。(我认为这绝对是正确的策略,但 JDBC 驱动程序供应商之间没有达成共识。)将autoCommitOnClose设置为 true 会导致提交未提交的挂起工作,而不是在连接关闭时回滚。[注意:由于规范在这个问题上非常不清楚,希望避免错误和不一致行为的应用程序作者应该确保在调用关闭之前明确提交或回滚所有事务。] [看“配置未解决的事务处理” ]

  • automaticTestTable

    默认值:空. 如果提供,c3p0 将创建一个指定名称的空表,并对该表使用查询来测试连接。如果提供了automaticTestTable,c3p0 将生成自己的测试查询,因此任何preferredTestQuery集都将被忽略。在 c3p0 创建后,您不应该使用命名表;它应该严格用于 c3p0 在测试您的连接时使用。(如果您定义自己的 ConnectionTester,它必须实现QueryConnectionTester 接口才能使该参数有用。)[请参阅“配置连接测试” ]

  • breakAfterAcquireFailure

    默认值:假. 如果为 true,如果在进行acquireRetryAttempts后无法从数据库中获取连接,则合并的数据源将声明自己已损坏并永久关闭。如果为 false,则无法获取连接将导致所有等待池获取连接的线程抛出异常,但数据源将保持有效,并将在调用getConnection()后尝试再次获取。[参见“配置数据库中断恢复” ]

  • checkoutTimeout

    默认值:0. 当连接池耗尽时,调用 getConnection() 的客户端将等待检入或获取连接的毫秒数。 零意味着无限期地等待。 设置任何正值将导致 getConnection() 调用超时并在指定的毫秒数后以 QLException 中断。

  • connectionCustomizerClassName

    默认值:空. ConnectionCustomizer接口实现 的完全限定类名 ,用户可以实现该接口以在从数据库获取连接时或在签出时设置连接,并可能在签入和销毁连接时进行清理。如果在 ConnectionCustomizer 的 onAcquire() 方法中设置了标准的 Connection 属性(holdability、readOnly 或 transactionIsolation),这些属性将覆盖 Connection 默认值。

  • connectionTesterClassName

    默认值:com.mchange.v2.c3p0.impl.DefaultConnectionTester. ConnectionTester 接口或QueryConnectionTester 实现的完全限定类名,如果您希望实例可以访问用户配置的preferredTestQuery。这可用于自定义 c3p0 DataSources 测试连接的方式,但是随着automaticTestTablepreferredTestQuery配置参数的引入,“自己动手”对大多数用户来说应该是矫枉过正了。[参见“配置连接测试”]

  • contextClassLoaderSource

    默认值:来电者必须是callerlibrarynone之一。确定如何确定 c3p0 生成的线程的contextClassLoader(请参阅java.lang.Thread)。如果调用者,c3p0-spawned 线程(辅助线程java.util.Timer线程)从引发池初始化的客户端线程继承它们的contextClassLoader 。如果是librarycontextClassLoader将是加载 c3p0 类的类。如果没有,则不会设置contextClassLoader(该属性将为null),这实际上意味着将使用系统 ClassLoader。当客户端应用程序将由应用程序服务器热重新部署时,调用者的默认设置有时会出现问题。当 c3p0 的线程持有来自第一个访问它们的客户端的contextClassLoader引用 时,当它在正在运行的 VM 中取消部署时,可能无法垃圾收集与该客户端关联的ClassLoader 。将此设置为可以解决这些问题。[参见“配置以避免客户端热重新部署时的内存泄漏”]不支持每用户覆盖。

  • dataSourceName

    默认值:如果配置了命名配置,则为配置名称,否则为池的“身份令牌”。每个 c3p0 池数据源都有一个dataSourceName,它有两个用途。它帮助用户通过 C3P0Registry找到数据源,它包含在 JMX mBeans 的名称中,以帮助跟踪和区分多个 c3p0 数据源,甚至跨应用程序或 JVM 重新启动。如果使用命名配置,则dataSourceName 默认为池的配置名称,否则为“身份令牌”(与每个 c3p0 数据源关联的不透明、保证唯一的字符串)。您可以将此属性更新为您认为方便的任何名称。 dataSourceName不能保证是唯一的——例如,从同一个命名配置创建的多个 DataSource 将共享同一个dataSourceName。但是,如果您打算使用dataSourceName,您可能希望确保 JVM 中所有池化的 DataSources 都具有唯一的名称。

  • debugUnreturnedConnectionStackTraces

    默认值:假。如果为真,并且如果unreturnedConnectionTimeout设置为正值,则池将捕获所有 Connection 检出的堆栈跟踪(通过 Exception),并且当未返回的检出连接超时时将打印堆栈跟踪。这旨在调试具有连接泄漏的应用程序,即偶尔无法返回连接的应用程序,导致池增长并最终耗尽(当池达到maxPoolSize并且所有连接都已签出并丢失时)。此参数应仅在调试时设置,因为捕获堆栈跟踪会减慢每次连接签出的速度。[请参阅“配置以调试和解决损坏的客户端应用程序” ]

  • driverClass

    默认值:空预期提供连接的 JDBC driverClass 的完全限定类名。c3p0 将预加载此处指定的任何类,以确保适当的 URL 可以通过java.sql.DriverManager解析为驱动程序的实例。如果您希望完全跳过 DriverManager解析并确保使用指定类的实例来提供连接,请使用 ```driverClass结合 forceUseNamedDriverClass。[另见jdbcUrl`。]不支持每用户覆盖。

  • extensions

    默认值:一个空的java.util.Map. 一个java.util.Map(原始类型),包含 为此 DataSource 定义 的任何用户定义的配置扩展的值。不支持每用户覆盖。

  • factoryClassLocation

    默认值:空。预期提供连接的 JDBC driverClass 的完全限定类名。 c3p0 将预加载此处指定的任何类,以确保适当的 URL 可以通过 java.sql.DriverManager 解析为驱动程序的实例。 如果您希望完全跳过 DriverManager 解析并确保使用指定类的实例来提供连接,请将 driverClass 与 forceUseNamedDriverClass.结合使用。 [另见 jdbcUrl。]

  • forceIgnoreUnresolvedTransactions

    默认值:假。强烈不推荐。将此设置为true可能会导致微妙和奇怪的错误。 这是一个糟糕的设置,除非绝对必要,否则不要管它。它用于解决损坏的数据库/JDBC 驱动程序,这些驱动程序不能正确支持事务,但无论如何都允许 Connections 的 autoCommit标志变为 false。如果您正在使用“部分”支持事务的数据库(这是矛盾的,因为事务的全部意义在于可靠且完整地执行操作,但尽管如此,这样的数据库仍然存在),如果您愿意忽略 Connections with 的事实自动提交 == 假可能处于事务中间并可能持有锁和其他资源,您可以关闭 c3p0 的明智默认行为,即通过回滚(默认)或提交来保护自身以及数据库的可用性和一致性(参见上面的c3p0.autoCommitOnClose )未解决的事务。仅当您确定使用的数据库允许 Connections 的 autoCommit 标志变为 false,但不提供其他有意义的事务支持时,才应将此设置为 true。否则将其设置为 true 只是一个坏主意。 [参见“配置未解决的事务处理” ]

  • forceSynchronousCheckins

    默认值:假。将此设置为true会强制同步签入连接,这在某些情况下可能会提高性能。通常,连接是异步签入的,以便客户端避免任何测试或自定义签入逻辑的开销。但是,异步签入会导致线程池拥塞,非常繁忙的池可能会发现客户端延迟等待签入完成。扩展numHelperThreads有助于管理线程池拥塞,但内存占用和切换成本限制了实际线程池大小。要减少线程池负载,您可以将 forceSynchronousCheckins设置为true。同步签入可能会提高整体性能 testConnectionOnCheckin设置为 false,并且不会在ConnectionCustomizeronCheckIn(...)方法中执行缓慢的工作。如果在签入时测试连接或执行其他缓慢的工作,则此设置将导致客户端在Connection.close()上体验该工作的开销,您必须在池性能的任何改进之间进行权衡。[参见“其他数据源配置” ]

  • forceUseNamedDriverClass

    默认值:假。设置参数driverClass会导致该类预加载并向java.sql.DriverManager注册。但是,它本身并不能确保所使用的驱动程序将是driverClass的实例,因为DriverManager 可能(在不寻常的情况下)知道可以处理指定jdbcUrl的其他驱动程序类。将此参数设置为 true 会导致 c3p0 忽略DriverManager并直接简单地实例化driverClass 。不支持每用户覆盖。

  • idleConnectionTestPeriod

    默认值:0。如果这是一个大于 0 的数字,c3p0 将每隔这个秒数测试所有空闲、合并但未检出的连接。[参见“配置连接测试” ]

  • initialPoolSize

    默认值:3。池在启动时将尝试获取的连接数。应该介于minPoolSizemaxPoolSize之间。[参见“基本池配置” ]

  • jdbcUrl

    默认值:空。可以并且应该从中获取连接的数据库的 JDBC URL。应通过java.sql.DriverManager解析 为适当的 JDBC 驱动程序(您可以确保通过设置加载并可用 driverClass),或者如果您希望指定直接使用哪个驱动程序(并避免DriverManager 解析),您可以将driverClassforceUseNamedDriverClass结合使用。除非您提供自己的非池化数据源,否则必须始终提供并适用于 JDBC 驱动程序,但已解决。不支持每用户覆盖。

  • maxAdministrativeTaskTime

    默认值:0。在 c3p0 的线程池将尝试中断明显挂起的任务之前的几秒。很少有用。c3p0 的很多功能不是由客户端线程执行的,而是由内部线程池异步执行的。c3p0 的异步性直接增强了客户端性能,并通过确保在非锁持有线程中执行慢速 jdbc 操作来最小化关键锁持有的时间长度。然而,如果这些任务中的一些“挂起”,即它们在很长一段时间内既不成功也不因异常而失败,c3p0 的线程池可能会耗尽并且管理任务会被备份。如果任务很慢,解决问题的最佳方法是增加线程数,通过numHelperThreads. 但是如果任务有时会无限期地挂起,您可以使用这个参数在任务超过设定的时间限制时强制调用任务线程的interrupt()方法。无论如何,c3p0 最终都会通过发出“APPARENT DEADLOCK”信号(您会在日志中看到它作为警告)从挂起的任务中恢复,替换线程池任务线程,并中断()原始线程。但是让池进入 APPARENT DEADLOCK 然后恢复意味着在某些时期内,c3p0 的性能将受到损害。因此,如果您看到这些消息,增加numHelperThreads 并设置maxAdministrativeTaskTime可能会有所帮助。最大管理任务时间应该足够大,以便任何从数据库获取连接、测试连接或销毁连接的合理尝试都有望在设定的时间内成功或失败。零(默认值)表示任务永不中断,这是大多数情况下最好和最安全的策略。如果任务只是很慢,请分配更多线程。如果任务永远挂起,请尝试找出原因,同时设置maxAdministrativeTaskTime可能会有所帮助。不支持每用户覆盖。

  • maxConnectionAge

    默认值:0。 单位为秒,有效的生存时间。 早于maxConnectionAge 的连接将被销毁并从池中清除。 这与 maxIdleTime 的不同之处在于它指的是绝对年龄。 即使一个没有太多空闲的连接,如果它超过 maxConnectionAge,也会从池中清除。 零表示不强制执行最大绝对年龄。

  • maxIdleTime

    默认值:0。连接在被丢弃之前可以保留在池中但未使用的秒数。零表示空闲连接永不过期。[参见“基本池配置” ]

  • maxIdleTimeExcessConnections

    默认值:0。超过 minPoolSize的连接在被剔除之前应被允许在池中保持空闲的秒数。 适用于希望积极减少打开连接数的应用程序,如果在峰值之后负载级别降低并且不再需要获取的连接,则将池缩小回 minPoolSize。 如果设置了 maxIdleTime,如果该参数要起作用,maxIdleTimeExcessConnections 应该更小。 零意味着没有执行,多余的连接不会被闲置。

  • maxPoolSize

    默认值:15。池在任何给定时间将维护的最大连接数。[参见“基本池配置” ]

  • maxStatements

    默认值:0。c3p0 的全局 PreparedStatement 缓存的大小。如果maxStatementsmaxStatementsPerConnection 都为零,则不会启用语句缓存。如果maxStatements为零但maxStatementsPerConnection 为非零值,将启用语句缓存,但不会强制执行全局限制,只有每个连接的最大值。 maxStatements控制所有连接缓存的语句总数。如果设置,它应该是一个相当大的数字,因为每个池连接都需要它自己的、不同的缓存语句群。作为指导,请考虑经常使用多少不同的 PreparedStatements 在您的应用程序中,将该数字乘以maxPoolSize以获得适当的值。尽管maxStatements是用于控制语句缓存的 JDBC 标准参数,但用户可能会发现 c3p0 的替代maxStatementsPerConnection使用起来更直观。[参见“配置语句池” ]

  • maxStatementsPerConnection

    默认值:0。c3p0 PreparedStatements 的数量将为单个池连接缓存。如果maxStatementsmaxStatementsPerConnection 都为零,则不会启用语句缓存。如果maxStatementsPerConnection为零但maxStatements 为非零值,将启用语句缓存,并强制执行全局限制,否则不会对单个连接的缓存语句数设置限制。如果设置,maxStatementsPerConnection 应设置为大约 经常使用的不同 PreparedStatements 的数量在您的应用程序中,加上两三个额外的如此不常见的语句不会强制剔除更常见的缓存语句。尽管maxStatements是用于控制语句缓存的 JDBC 标准参数,但用户可能会发现maxStatementsPerConnection使用起来更直观。[参见“配置语句池” ]

  • minPoolSize

    默认值:3。池在任何给定时间将维护的最小连接数。[参见“基本池配置” ]

  • numHelperThreads

    默认值:3。c3p0 是非常异步的。 慢速 JDBC 操作通常由不持有争用锁的辅助线程执行。 通过允许同时执行多个操作,将这些操作分散到多个线程上可以显着提高性能。

  • overrideDefaultUser

    默认值:空。当用户调用默认的 getConnection() 方法时,强制使用 PooledDataSources 应该使用的用户名。当应用程序从非 c3p0 未合并的数据源合并连接时,这主要有用。使用ComboPooledDataSource或包装任何 c3p0 实现的非池化数据源的应用程序可以使用简单的 用户属性。不支持每用户覆盖。

  • overrideDefaultPassword

    默认值:空。当用户调用默认的 getConnection() 方法时,强制使用 PooledDataSources 应该使用的密码。当应用程序从非 c3p0 未合并的数据源合并连接时,这主要有用。使用ComboPooledDataSource或包装任何 c3p0 实现的非池化数据源的应用程序可以使用简单 密码属性。不支持每用户覆盖。

  • password

    默认值:空。对于使用ComboPooledDataSource或任何 c3p0 实现的非池化数据源的应用程序——DriverManagerDataSourceDataSources.unpooledDataSource( ... )返回的数据源——定义将用于数据源的默认 getConnection()方法的密码。(另见用户。)不支持每用户覆盖。

  • preferredTestQuery

    默认值:空。如果正在使用默认的ConnectionTester(或 QueryConnectionTester的某些其他实现,或者更好的是FullQueryConnectionTester) ,则定义将为所有连接测试执行的查询。定义将在您的数据库中快速执行的preferredTestQuery 可能会显着加快连接测试。(如果未设置preferredTestQuery ,则默认的 ConnectionTester 会在 Connection 的 DatabaseMetaData 上执行getTables()调用。根据您的数据库,这可能比“正常”数据库查询执行得更慢。) 注意:您的preferredTestQuery所针对的表在初始化数据源*之前*,将运行的必须存在于数据库模式中。如果您的应用程序定义了自己的模式,请尝试使用automaticTestTable [参见“配置连接测试” ]

  • privilegeSpawnedThreads

    默认值:假。如果为true,c3p0 生成的线程将具有与 c3p0 库类关联的java.security.AccessControlContext 。默认情况下,c3p0 生成的线程(辅助线程java.util.Timer线程)从引发池初始化的客户端线程继承它们的 AccessControlContext 。这有时会成为一个问题,尤其是在支持客户端应用程序热重新部署的应用程序服务器中。如果 c3p0 的线程持有第一个访问它们的客户端对AccessControlContext的引用,则可能无法对ClassLoader进行垃圾回收 在正在运行的 VM 中取消部署时与该客户端关联。此外,客户端线程可能缺乏足够的权限来执行 c3p0 所需的操作。将此设置为true可以解决这些问题。[参见“配置以避免客户端热重新部署时的内存泄漏”]不支持每用户覆盖。

  • propertyCycle

    默认值:0。强制执行用户配置约束之前的最长时间(以秒为单位)。确定执行maxConnectionAgemaxIdleTimemaxIdleTimeExcessConnectionsunreturnedConnectionTimeout的频率。c3p0 定期检查连接的年龄以查看它们是否超时。该参数决定周期。零表示自动:合适的周期将由 c3p0 确定。[您可以调用c3p0 ``PooledDataSource上的getEffectivePropertyCycle...()方法 来查找自动选择的周期。]

  • statementCacheNumDeferredCloseThreads

    默认值:0。如果设置为大于 0 的值,语句缓存将跟踪何时使用连接,并且仅在其父连接未被使用时才销毁语句。尽管在使用父 Connection 时关闭 Statement 正式符合规范,但某些数据库和/或 JDBC 驱动程序(最著名的是 Oracle)无法很好地处理这种情况并冻结,从而导致死锁。将此参数设置为正值应该可以消除该问题。仅当您观察到 c3p0 对 close() 缓存语句的尝试冻结时才应设置此参数(通常您会在日志中看到APPARENT DEADLOCKS)。如果设置,这个参数应该几乎总是设置为1. 基本上,如果您需要多个专用于销毁缓存语句的线程,您应该设置maxStatements 和/或maxStatementsPerConnection,这样您就不会如此快速地处理语句。[参见“配置语句池” ]不支持每用户覆盖。

  • testConnectionOnCheckin

    默认值:假。如果为 true,将在每次连接签入时异步执行操作以验证连接是否有效。与idleConnectionTestPeriod结合使用以进行非常可靠、始终异步的连接测试。此外,设置automaticTestTablepreferredTestQuery通常会加速所有连接测试。[参见“配置连接测试” ]

  • testConnectionOnCheckout

    默认值:假。如果为真,将在每次连接检查时执行操作以验证连接是否有效。 如果将其设置为*true ,请确保设置有效的* preferredTestQuery *或* automaticTestTable 。 *在每个客户端结帐时执行(昂贵的)默认连接测试会损害客户端性能。* 在结帐时测试连接是最简单和最可靠的连接测试形式,但为了获得更好的性能,请考虑使用idleConnectionTestPeriod定期验证连接。[参见 ````“配置连接测试” ]

  • unreturnedConnectionTimeout

    默认值:0秒。如果设置,如果应用程序在指定的时间段内签出但未能签入[即close()] Connection,则池将毫不客气地销毁() Connection。这允许偶尔发生连接泄漏的应用程序得以生存,而不是最终耗尽连接池。这是一种耻辱。零意味着没有超时,应用程序应该关闭()自己的连接。显然,如果设置了一个非零值,那么它的值应该比任何 Connection 应该被合理地签出的时间都长。否则,池偶尔会终止正在使用的连接,这很糟糕。 这基本上是一个坏主意,但它是一个普遍要求的功能。修复您的 $%!@% 应用程序,以免它们泄漏连接! debugUnreturnedConnectionStackTraces找出连接被签出的位置,这些连接不会返回到池中! [请参阅“配置以调试和解决损坏的客户端应用程序”]

  • user

    默认值:空对于使用ComboPooledDataSource或任何 c3p0 实现的非池化数据源的应用程序——DriverManagerDataSource或由DataSources.unpooledDataSource()返回的数据源——定义将用于数据源的默认 getConnection()方法的用户名。(另请参阅密码。)不支持每用户覆盖。

其他属性

以下配置属性会影响整个 c3p0 库的行为。它们可以在c3p0.properties文件或HOCON(类型安全配置)文件中设置为系统属性。

定位和解析配置信息

通常,c3p0 的配置信息位于应用程序 CLASSPATH 顶层的 c3p0-config.xml 或 c3p0.properties 文件中。但是,如果您希望将配置信息放在别处,您可以将 c3p0 配置信息(仅限XML 文件格式!)放在应用程序可见的文件系统中的任何地方。只需将以下属性设置为 XML 配置文件的完整绝对路径:

  • com.mchange.v2.c3p0.cfg.xml

如果您将此属性设置为以“ classloader: ” 开头的值,c3p0 将搜索 XML 配置文件作为 ClassLoader 资源,即在您在类路径下指定的任何位置,包括 jar 文件META-INF目录。

由于围绕自由解析 XML 引用的安全问题,c3p0 现在默认情况下极其严格地解析 XML 文件。除其他外,它不再扩展 XML 配置文件中的实体引用。实体引用可能会被默默地忽略!它还不再支持 xml 包含,如果 JVM 的底层 XML 库支持,它会尝试禁用任何内联文档类型定义。在极少数情况下,配置有意依赖实体引用扩展、DTD、XML 包含或其他危险功能,您可以重新打开许可解析,恢复 c3p0 的传统行为。*确保您了解安全问题,并信任您对 XML 配置文件的控制和完整性,然后再恢复旧的、允许的行为。*然后,如果您愿意,可以将以下属性设置为true

  • com.mchange.v2.c3p0.cfg.xml.usePermissiveParser

这将恢复 c3p0 在 c3p0-0.9.5.3 之前的版本中默认使用的 XML 配置文件的传统自由解析。(从版本 0.9.5.4 开始, com.mchange.v2.c3p0.cfg.xml.usePermissiveParser取代了 0.9.5.3 中引入的现已弃用com.mchange.v2.c3p0.cfg.xml.expandEntityReferences,因为它远不止实体参考扩展现在受到限制。)

记录相关的属性

以下属性影响 c3p0 的日志记录行为。 有关具体信息, 请参阅上面的配置日志记录。

  • com.mchange.v2.log.MLog
  • com.mchange.v2.log.jdk14logging.suppressStackWalk
  • com.mchange.v2.log.NameTransformer
  • com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL

配置 JMX

以下属性影响 c3p0 的 JMX 管理接口。请参阅 上面的通过 JMX 配置和管理 c3p0以获取更多信息。

  • com.mchange.v2.c3p0.management.ExcludeIdentityToken
  • com.mchange.v2.c3p0.management.RegistryName
  • com.mchange.v2.c3p0.management.ManagementCoordinator

配置VMID

漂亮好还是正确好?从 c3p0-0.9.1 开始,c3p0 有点不情愿地选择了正确性。

这是交易。每个 c3p0 数据源都分配了一个唯一的“身份令牌”,用于确保同一 PooledDataSource 的多个 JNDI 查找始终返回相同的实例,即使 JNDI 名称服务器存储序列化或引用实例。以前,c3p0 很高兴生成的 ID 在单个 VM 中是唯一的(在 c3p0-0.9.1 之前,它甚至没有做到这一点)。但从理论上讲,一个 VM 可能会查找由两个不同的 VM 生成的两个不同的 DataSources,这不太可能巧合具有相同的“身份令牌”,从而导致错误,因为两个 DataSources 之一偷偷地替换了第二个。尽管这个假设性问题在实践中从未被报告过,但 c3p0 通过在其身份令牌前添加 VMID 来解决它。这使它们又长又丑,

如果你不喜欢又长又丑的 VMID,你可以自己设置,或者你可以完全使用以下属性关闭这个假设的非问题的解决方案:

  • com.mchange.v2.c3p0.VMID

将其设置为NONE以关闭 VMID,将其设置为AUTO以让 c3p0 生成 VMID,或提供任何其他字符串来设置将直接使用的 VMID。默认为自动

配置 DefaultConnectionTester.isValidTimeout

在 JDBC 4+ isValid(...)测试将被 c3p0 内置的 DefaultConnectionTester(见下文)使用的情况下,默认情况下测试永远不会超时。如果您希望测试超时并失败,请设置以下键

  • com.mchange.v2.c3p0.impl.DefaultConnectionTester.isValidTimeout

到所需的超时时间,以秒为单位。

配置 DefaultConnectionTester.QuerylessTestRunner

当您提供preferredTestQueryautomaticTestTable参数 时,c3p0 的内置 DefaultConnectionTester 会做正确且显而易见的事情。但是当它没有用户确定的查询来运行以测试连接时,c3p0 应该做什么就不那么清楚了。在 JDBC 3 API 中,没有直接、可靠的方法来测试 JDBC 连接。c3p0 的 DefaultConnectionTester 采用了非常保守的技术,使用 Connection 来查询 DatabaseMetaData,因为这代表了对数据库的实时查询,可以在不知道数据库模式的情况下执行。不幸的是,这种技术通常非常非常慢。

幸运的是,从 0.9.5 版开始,c3p0 支持使用新的Connection.isValid()方法对 JDBC 4 API 进行测试。这是由 JDBC 驱动程序提供商指定和实施的快速、可靠的测试。

尽管很少有必要,但用户现在可以在没有通过以下属性设置 preferredTestQueryautomaticTestTable的情况下准确指定 DefaultConnectionTester 的行为方式:

  • com.mchange.v2.c3p0.impl.DefaultConnectionTester.querylessTestRunner

此属性的可能值包括

  • METADATA_TABLESEARCH

    这是 c3p0 的非常慢但非常可靠的传统默认连接测试。它甚至可以使用非常旧的 JDBC 驱动程序。

  • IS_VALID

    这使用新的 JDBC 4 API 来执行驱动程序定义的连接测试。但是,如果它与旧的JDBC 3 驱动程序一起使用,则会引发AbstractMethodError 。

  • SWITCH

    这首先尝试新的 JDBC 4 连接测试(如IS_VALID),但会捕获任何AbstractMethodError并在必要时回退到METADATA_TABLESEARCH 。

  • THREAD_LOCAL

    这将检查新的Connection.isValid()方法是否可用于它测试的任何Connection实现,并存储一个``ThreadLocal ``WeakHashMap以跟踪哪些 Connection 实现支持该方法。然后,它查询地图并根据需要运行快速IS_VALID测试或通用METADATA_TABLESEARCH 测试。

您还可以提供 DefaultConnectionTester.QuerylessTestRunner接口实现的完全限定类名,并定义您自己的行为,无论您想做什么。你的类应该是公共的,有一个公共的无参数构造函数,并且是线程安全的和可共享的。(c3p0 池通常只使用一个 ConnectionTester 来测试它的所有连接,通常是同时进行。)例如,请参阅 c3p0 源代码中的内置实现

默认值是SWITCH,几乎总是可以的。

真的,你几乎不应该费心去设置这个属性。如果您使用旧的 JDBC 驱动程序并希望消除尝试isValid()方法然后捕获AbstractMethodError的小开销,您可以通过将其值设置为METADATA_TABLESEARCH来实现。但是,当设置一个preferredTestQuery并完全避免无查询测试的速度快得多的方法时,为什么还要麻烦呢?如果您想做一些完全不同的事情,您可以实现自己的DefaultConnectionTester.QuerylessTestRunner。或者您可以直接实现ConnectionTester,并设置参数connectionTesterClassName

实验性质

c3p0-0.9.1 包含异步连接获取的新实现,在数据库获取尝试(无论出于何种原因)偶尔会失败的情况下,应该会提高 c3p0 的性能和资源利用率。新的实现应该明显优于“传统的”Connection 获取策略,但是在 c3p0-0.9.1 开发周期中添加得太晚了,无法在默认情况下进行全面测试和启用。鼓励用户尝试新的实现,因为它更好,并且有助于解决任何未预料到的问题。

有关新实现及其旨在克服的资源瓶颈的完整描述,请参阅c3p0-0.9.1-pre11CHANGELOG条目。

从 c3p0-0.9.2 开始,此功能默认启用。要恢复为传统的 Connection 获取行为,请将以下参数设置为false

  • com.mchange.v2.resourcepool.experimental.useScatteredAcquireTask

附录B:配置文件等

c3p0 配置参数可以 通过简单的 Java 属性文件、类型安全的“HOCON”文件XML 配置文件系统属性直接在 Java 代码中设置。任何一种方式都有效(不过,XML 配置最强大,因为它支持多个命名配置和每个用户覆盖。选择最适合你的方式。

通过c3p0.properties覆盖 c3p0 默认值

要覆盖库的内置默认值,请创建一个名为c3p0.properties的文件 并将其放在类路径或类加载器的“根目录”中。对于典型的独立应用程序,这意味着将文件放在CLASSPATH 环境变量中命名的目录中。对于典型的 Web 应用程序,该文件应放在 WEB-INF/classes中。通常,该文件必须在加载 c3p0 的 jar 文件的类加载器中以名称c3p0.properties作为类加载器资源可用。查看java.lang.Classjava.lang.ClassLoaderjava.util.ResourceBundle的 API 文档(特别是getResource...方法)如果这是陌生的。

c3p0.properties 的格式应该是普通的 Java Properties 文件格式,其键是 c3p0 可配置属性。请参阅附录A。具体细节。下面生成了一个示例c3p0.properties文件:

# 打开语句池
c3p0.maxStatements=150
# 关闭超过半小时未使用的池连接 
c3p0.maxIdleTime=1800 

使用“HOCON”(typesafe-config)配置文件覆盖 c3p0 默认值

Typesafe 定义了一种非常好的配置文件格式,称为“HOCON”。

c3p0 不包含 Typesafe 的库,但如果您将它与您的应用程序捆绑在一起,c3p0 将支持这种格式的配置。您可以将 c3p0 配置放在标准的/application.conf/reference.conf文件中,或者您可以使用特殊的/c3p0.conf文件。(这些文件必须作为顶级 ClassLoader 资源放置,见上文。) /application.json/application.propertiesc3p0.json也受支持,来自/c3p0.properties的替换将得到解决。Typesafe 配置库可以从 Maven Central Repository 下载

请记住,仅当您明确将 Typesafe 配置库与您的应用程序捆绑在一起时,HOCON 配置才受支持。该库不包含在 c3p0 的二进制分发版中,也不会作为传递依赖项随 c3p0 下载!

以下是在 HOCON 中设置 c3p0 配置的一些示例:

c3p0 {
  # turn on statement pooling
  maxStatements=150
	
  # close pooled Connections that go unused for
  # more than half an hour
  maxIdleTime=1800
}

请注意,您必须以某种方式在 c3p0 范围内显式指定普通配置参数,即使在c3p0.conf文件中也是如此。“点符号”可以等同于作用域:

# equivalent to the example above, and
# identical to the properties file format.

c3p0.maxStatements=150
c3p0.maxIdleTime=1800

同样,下面的两个配置也是等效的

# properties-file-ish specification
com.mchange.v2.log.MLog=com.mchange.v2.log.log4j.Log4jMLog

# scoped specification of the same
com {
  mchange {
    v2 {
      log {
        MLog="com.mchange.v2.log.log4j.Log4jMLog"
      }
    }
  }
}

使用系统属性覆盖 c3p0 默认值

c3p0 属性也可以定义为系统属性,使用相同的“c3p0”。c3p0.properties文件 中指定的属性的前缀。

swaldman% java -Dc3p0.maxStatements=150 -Dc3p0.maxIdleTime=1800 example.MyC3P0App

系统属性覆盖 c3p0.properties 中的设置。有关详细信息 ,请参阅 配置设置的优先顺序。

在c3p0.properties 文件中合法 的任何键作为系统属性都是合法的,包括可能定义了 namedper-useruser-defined-extension 参数的键。

通过c3p0-config.xml覆盖 c3p0 默认值

您可以将 XML 配置文件用于所有 c3p0 配置,包括默认配置、命名配置、每个用户覆盖和配置扩展。

默认情况下,c3p0 将在其类加载器的资源路径中查找名为“/c3p0-config.xml”的 XML 配置文件。这意味着 XML 文件应直接放置在应用程序 CLASSPATH、WEB-INF/classes 或某个类似位置中直接命名的 jar 文件中。

如果您不想将您的配置与您的代码捆绑在一起,您可以通过系统属性com.mchange.v2.c3p0.cfg.xml为 c3p0 的配置文件指定一个普通的文件系统位置。(您还可以使用此属性指定 ClassLoader 资源路径中的替代位置,例如META-INF。请参阅定位配置信息。)

这是一个示例c3p0-config.xml文件:

<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>

配置设置的优先级

c3p0 现在允许以多种不同的方式和位置设置配置参数。幸运的是,有一个明确的优先顺序可以确定在发生冲突设置时“采用”哪个配置。从概念上讲,c3p0 使用它找到的第一个设置从上到下沿着这个列表向下排列。

大多数应用程序永远不会使用每个用户或命名配置。对于这些应用程序,我们提供了一个简化的优先级层次结构:

  1. 以编程方式设置的配置值。
  2. 在系统属性中设置的配置值。
  3. 配置值取自c3p0-config.xml文件的默认配置。
  4. c3p0.properties文件中指定的配置值
  5. c3p0.json文件中的配置值,当且仅当 Typesafe 配置库可用时。
  6. c3p0.conf文件中的配置值,当且仅当 Typesafe 配置库可用时。
  7. application.properties文件中的配置值,当且仅当 Typesafe 配置库可用时。
  8. application.json文件中的配置值,当且仅当 Typesafe 配置库可用时。
  9. application.conf文件中的配置值,当且仅当 Typesafe 配置库可用时。
  10. reference.conf文件中的配置值,当且仅当 Typesafe 配置库可用时。
  11. c3p0 的硬编码默认值。

对于确实使用命名和每用户配置的应用程序,这里是完整的、规范的优先级层次结构:

  1. 通过以下方式以编程方式设置用户特定的覆盖:

    请注意,以编程方式设置用户特定的覆盖会

    替换

    从其他来源获取的所有用户特定的配置。如果您想将编程更改与预配置的覆盖合并,则必须使用

    getUserOverridesAsString()

    并在替换之前修改原始设置。

  2. 从数据源的命名配置(在c3p0-config.xml中指定)获取的特定于用户的覆盖

  3. 从默认配置中获取的特定于用户的覆盖(在c3p0-config.xml中指定)

  4. 以编程方式设置的非用户特定值。

  5. 从数据源的命名配置中获取的非用户特定值(在c3p0-config.xml中指定)

  6. 配置值的系统属性设置。

  7. 从默认配置中获取的非用户特定值(在c3p0-config.xml中指定)

  8. c3p0.conf文件中的配置值,当且仅当 Typesafe 配置库可用时。

  9. c3p0.properties文件中指定的配置值

  10. application.conf文件中的配置值 ,当且仅当 Typesafe 配置库可用时。

  11. reference.conf文件中的配置值 ,当且仅当 Typesafe 配置库可用时。

  12. c3p0 的硬编码默认值。

附录 C:特定于 Hibernate 的注释

Hibernate 的 C3P0ConnectionProvider 重命名了 7 个 c3p0 配置属性,如果在你的 hibernate 配置中设置了这些属性,它们将覆盖你可能在c3p0.properties文件中设置的任何配置:

c3p0-原生属性名称 休眠配置键
c3p0.acquireIncrement 休眠.c3p0.acquire_increment
c3p0.idleConnectionTestPeriod hibernate.c3p0.idle_test_period
c3p0.initialPoolSize not available – uses minimum size
c3p0.maxIdleTime hibernate.c3p0.timeout
c3p0.maxPoolSize hibernate.c3p0.max_size
c3p0.max语句 hibernate.c3p0.max_statements
c3p0.minPoolSize hibernate.c3p0.min_size
c3p0.testConnectionOnCheckout hibernate.c3p0.validate仅限 hibernate 2.x!

您可以使用前缀hibernate.c3p0 在您的休眠配置中设置任何 c3p0 属性。例如

hibernate.c3p0.unreturnedConnectionTimeout=30 
hibernate.c3p0.debugUnreturnedConnectionStackTraces=true

可能设置为帮助调试连接泄漏

您始终可以在c3p0.propertiesc3p0-config.xml文件中设置 c3p0 配置(请参阅“通过 c3p0.properties 覆盖 c3p0 默认值”“通过 c3p0-config.xml 覆盖 c3p0 默认值”),但在 Hibernate 配置中设置任何配置文件将覆盖 c3p0-native 配置!


附录 D:在 Tomcat 中配置 c3p0 数据源

**注意:**如果您在 Tomcat 上遇到内存泄漏,
请参阅“配置以避免客户端热重新部署时的内存泄漏”。

**TL; DR:**将privilegeSpawnedThreads设置为true并将contextClassLoaderSource设置为library

您可以轻松配置 Apache 的 Tomcat Web 应用程序服务器以使用 c3p0 池化数据源。下面是一个 Tomcat 5.0 示例配置,可帮助您入门。它是 Tomcat 的conf/server.xml文件的一个片段,应该对其进行修改以适应并放置在<Context>元素中。

<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,尝试如下操作(感谢 Carl F. Hall 提供的示例!):

	<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 文件中声明您的 DataSource 引用:

<resource-ref>
  <res-ref-name>jdbc/pooledDS</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>
      

您可以像这样从 Web 应用程序中的代码访问数据源:

InitialContext ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("java:comp/env/jdbc/pooledDS");

仅此而已!


附录 E:JBoss 特定说明

在 JBoss 中使用 c3p0:

  1. 将 c3p0 的 jar 文件放在 jboss 服务器实例的lib目录中(例如${JBOSS_HOME}/server/default/lib
  2. 修改下面的文件,将它保存为c3p0-service.xml在 你的 jboss 服务器的部署目录中(例如``${JBOSS_HOME}/server/default/deploy)。请注意,此文件中的参数必须大写,否则它们的定义如上所述。

注意: 支持c3p0-0.9.1之前的c3p0 jboss的用户请点击这里!

<?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>

附录 F:Oracle 特定的 API:createTemporaryBLOB() 和 createTemporaryCLOB()

Oracle thin JDBC 驱动程序提供了一个非标准 API,用于创建临时 BLOB 和 CLOB,这需要用户调用原始的、特定于 Oracle 的 Connection 实现的方法。高级用户可能会使用上述原始连接操作 来访问此功能,但在单独的 jar 文件 (c3p0-oracle-thin-extras-0.9.5.5.jar )中提供了一个便利类,以便更轻松地访问此功能。有关详细信息,请参阅 com.mchange.v2.c3p0.dbms.OracleUtils的API 文档

0

评论区