使用 C3P0 的 JDBC 连接池
Posted
技术标签:
【中文标题】使用 C3P0 的 JDBC 连接池【英文标题】:JDBC Connection pooling using C3P0 【发布时间】:2010-11-30 07:55:42 【问题描述】:以下是我获取数据库连接的帮助类:
我已经使用了 here 中描述的 C3P0 连接池。
public class DBConnection
private static DataSource dataSource;
private static final String DRIVER_NAME;
private static final String URL;
private static final String UNAME;
private static final String PWD;
static
final ResourceBundle config = ResourceBundle
.getBundle("props.database");
DRIVER_NAME = config.getString("driverName");
URL = config.getString("url");
UNAME = config.getString("uname");
PWD = config.getString("pwd");
dataSource = setupDataSource();
public static Connection getOracleConnection() throws SQLException
return dataSource.getConnection();
private static DataSource setupDataSource()
ComboPooledDataSource cpds = new ComboPooledDataSource();
try
cpds.setDriverClass(DRIVER_NAME);
catch (PropertyVetoException e)
e.printStackTrace();
cpds.setJdbcUrl(URL);
cpds.setUser(UNAME);
cpds.setPassword(PWD);
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
return cpds;
在 DAO 中,我将编写如下内容:
try
conn = DBConnection.getOracleConnection();
....
finally
try
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (conn != null)
conn.close();
catch (SQLException e)
logger
.logError("Exception occured while closing cursors!", e);
现在,我的问题是除了关闭 finally 块中列出的游标(连接/语句/resultSet/preparedStatement)之外,我是否应该费心做任何其他清理工作。
什么是this 清理?我应该在何时何地进行此操作?
如果您发现以上代码有什么问题,请指出。
【问题讨论】:
在JDK 7中你不需要关闭preparedStatement,它实现了AutoClosable。 due to this post @AminSh 您的评论具有误导性,实现AutoClosable
的类并不意味着您不需要关闭它。它只是让您可以选择在 try-with-resources
块中使用该类的对象。
【参考方案1】:
对于池化数据源,池中的连接实际上并没有关闭,它们只是返回到池中。但是,当应用程序关闭时,这些与数据库的连接应该正确且实际关闭,这就是最终清理的用武之地。
顺便说一句,c3p0 项目几乎已经死了,我建议你改用Apache Commons DBCP,它仍在维护中。
【讨论】:
@skaffman:在阅读了与您在这里所说的几乎相反的内容后,我正要从 DBCP 切换到 C3P0:***.com/questions/520585/…。现在我不太确定 - 似乎这两个项目最近都没有太多 TLC。 使用 BoneCP,非常活跃,优秀的工具,良好的文档,非常快。我们在非常高流量的站点使用它并且没有问题。 在这篇评论中,关于 c3p0 死亡的谣言似乎被夸大了:sourceforge.net/projects/c3p0(最后一次 repo 更新是 2014-04-04)。 数据库连接池不需要数量惊人的功能。一旦它完成并修复了它最突出的错误,你不应该期望有太多的活动,即使它的维护者仍然关心它。 我在2018年还在使用c3p0连接池。它解决了我由于dbcp而出现的问题。【参考方案2】:DAO 不应负责获取与数据库的连接。他们无法知道它们何时被用作更大交易的一部分。您应该将数据源或连接实例传递到 DAO。
如果在 finally 块中对 close 的任何调用抛出异常,则不会调用后面的任何调用。每个都需要在自己的 try/catch 块中。我将它们作为静态方法放入实用程序类中。
【讨论】:
【参考方案3】:代码对我来说看起来不错,但我会编写一个辅助方法来执行关闭操作,否则你会在每个 DAO 或方法中得到这个冗长的 finally 块。也许您应该在 close 操作周围编写三个单独的 try-catch-blocks,以确保无论语句和结果集是否引发了执行,连接都已关闭。还要注意javadoc says
当一个 Statement 对象关闭时,其当前的 ResultSet 对象(如果存在)也将关闭。
所以你不需要关闭上面例子中的结果集,但是你可以。
链接清理方法用于关闭数据源,这在大多数项目中是不需要的,因为只要您的应用正在运行,DS 就会存在。
【讨论】:
【参考方案4】:我使用 Play Framework 和 Scala,所以下面的例子是在 play 项目中。
步骤 1。配置
在 build.sbt 中,如果你使用 mysql/hive 作为数据库,你需要添加这些属性。
libraryDependencies ++ = Seq (
jdbc,
"mysql" % "mysql-connector-java" % "5.1.31",
"org.apache.hive" % "hive-jdbc" % "0.12.0",
"com.mchange" % "c3p0" % "0.9.2.1"
)
步骤 2。如何访问它?您需要导入 c3p0 库。
import com.mchange.v2.c3p0.ComboPooledDataSource
第 3 步。然后你需要创建实例。
val cpds = new ComboPooledDataSource()
cpds.setDriverClass(...)
cpds.setJdbcUrl(...)
cpds.setUser(...)
cpds.setPassword(...)
第四步。你得到一个连接
cpds.getConnection
【讨论】:
以上是关于使用 C3P0 的 JDBC 连接池的主要内容,如果未能解决你的问题,请参考以下文章