C3P0 导致线程关闭
C3P0 causing threads to close
我有一个奇怪的问题。我有一个实用程序 class 可以保持连接并具有准备语句的功能。然后语句 运行、关闭,一切正常。
但是,当我尝试使用 ComboPooledDataSource 添加连接池时,我的线程关闭了。我调试了它,我可以看到一些查询已成功执行,但突然间一切都关闭了,只剩下 c3p0 线程 运行。没有抛出异常。
我尝试将池设置为单个连接以尽可能地模仿工作代码,但也失败了。如果我将连接成员设置为来自池的连接,一切正常,但如果我尝试直接从池中使用,我会得到上面概述的行为。
下面是一些示例代码:
class DBUtilityClass
{
private java.sql.Connection connection;
private ComboPooledDataSource connectionPool;
public void DBUtilityClass()
{
connect();
}
private void connect()
{
connectionPool = new ComboPooledDataSource();
connectionPool.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver
connectionPool.setJdbcUrl(urlString.toString());
connectionPool.setUser(user);
connectionPool.setPassword(password);
connectionPool.setAutoCommitOnClose(true);
connectionPool.setInitialPoolSize(1);
connectionPool.setMinPoolSize(1);
connectionPool.setAcquireIncrement(1);
connectionPool.setMaxPoolSize(1);
}
//Version 1 - this works if I set the connection in the constructor
//or if I connect the connection manually without using the pool
public Connection getConnection()
{
connection.setAutoCommit(true);
return connection;
}
//Version 2 - This fails
public Connection getConnection()
{
Connection temp = connectionPool.getConnection();
temp.setAutoCommit(true);
return temp;
}
public PreparedStatement getPreparedStatement(String sql)
{
Connection temp = getConnection();
return temp.prepareStatement(sql);
}
}
您 class 中的函数 public PreparedStatement getPreparedStatement(String sql)
是一个 Connection
漏洞。每次调用它时,都会从池中取出一个 Connection
,但引用会被删除,因此它永远不会 close()
ed 并返回到池中。
(很抱歉在上面的评论中我花了这么长时间才看到这个!)
当有一个共享 Connection
时,没问题,一个连接保持签出状态。但是,当您像使用池一样,及时检出连接并且不缓存它们时,您必须确保在完成后 close()
它们。
确保对 getConnection()
的每个调用都与对 close()
的调用相匹配。最简单的方法是
- 不要在此处使用 getPreparedStatement(...)` 函数,只需使用 Connections
- 使用try-with-resources
try( Connection conn = myDBUtilityInstance.getConnection ) {
try( PreparedStatement ps = conn.prepareStatement( sql ) ) {
// do work here
}
}
我有一个奇怪的问题。我有一个实用程序 class 可以保持连接并具有准备语句的功能。然后语句 运行、关闭,一切正常。
但是,当我尝试使用 ComboPooledDataSource 添加连接池时,我的线程关闭了。我调试了它,我可以看到一些查询已成功执行,但突然间一切都关闭了,只剩下 c3p0 线程 运行。没有抛出异常。
我尝试将池设置为单个连接以尽可能地模仿工作代码,但也失败了。如果我将连接成员设置为来自池的连接,一切正常,但如果我尝试直接从池中使用,我会得到上面概述的行为。
下面是一些示例代码:
class DBUtilityClass
{
private java.sql.Connection connection;
private ComboPooledDataSource connectionPool;
public void DBUtilityClass()
{
connect();
}
private void connect()
{
connectionPool = new ComboPooledDataSource();
connectionPool.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver
connectionPool.setJdbcUrl(urlString.toString());
connectionPool.setUser(user);
connectionPool.setPassword(password);
connectionPool.setAutoCommitOnClose(true);
connectionPool.setInitialPoolSize(1);
connectionPool.setMinPoolSize(1);
connectionPool.setAcquireIncrement(1);
connectionPool.setMaxPoolSize(1);
}
//Version 1 - this works if I set the connection in the constructor
//or if I connect the connection manually without using the pool
public Connection getConnection()
{
connection.setAutoCommit(true);
return connection;
}
//Version 2 - This fails
public Connection getConnection()
{
Connection temp = connectionPool.getConnection();
temp.setAutoCommit(true);
return temp;
}
public PreparedStatement getPreparedStatement(String sql)
{
Connection temp = getConnection();
return temp.prepareStatement(sql);
}
}
您 class 中的函数 public PreparedStatement getPreparedStatement(String sql)
是一个 Connection
漏洞。每次调用它时,都会从池中取出一个 Connection
,但引用会被删除,因此它永远不会 close()
ed 并返回到池中。
(很抱歉在上面的评论中我花了这么长时间才看到这个!)
当有一个共享 Connection
时,没问题,一个连接保持签出状态。但是,当您像使用池一样,及时检出连接并且不缓存它们时,您必须确保在完成后 close()
它们。
确保对 getConnection()
的每个调用都与对 close()
的调用相匹配。最简单的方法是
- 不要在此处使用 getPreparedStatement(...)` 函数,只需使用 Connections
- 使用try-with-resources
try( Connection conn = myDBUtilityInstance.getConnection ) {
try( PreparedStatement ps = conn.prepareStatement( sql ) ) {
// do work here
}
}