使用 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 连接池的主要内容,如果未能解决你的问题,请参考以下文章

C3P0连接池的使用

C3P0连接池操作数据库

JDBC连接池C3P0

C3P0连接池的使用

c3p0 数据库连接池

c3p0 连接池