C3P0使用JDBC连接池技术

31
以下是我的助手类以获取DB连接:
我使用了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块中关闭列出的游标(connection/statement/resultSet/preparedStatement)之外,我是否应该进行任何其他清理?
什么是这个清理?何时和在哪里应该进行?
如果您在上述代码中发现任何错误,请指出。

在JDK 7中,您不需要关闭preparedStatement,它实现了AutoClosable。由于此帖子 - Amin Sh
1
@AminSh 你的评论有误导性,实现 AutoClosable 接口的类并不意味着 你不需要关闭 它。它只是给你在 try-with-resources 块中使用该类对象的选项。 - Miss Chanandler Bong
4个回答

27

使用数据池的时候,连接并没有被真正关闭,它们只是被返回到池中。然而,当应用程序关闭时,那些连接到数据库的连接应该被适当地关闭,这就是最终清理工作的作用。

顺便提一下,c3p0项目基本上已经死亡了,我建议你使用Apache Commons DBCP代替,因为它仍在维护。


7
@skaffman: 在阅读了这里的内容后,我本来打算从DBCP切换到C3P0的,因为它几乎与你在这里所说的相反:https://dev59.com/pXRB5IYBdhLWcg3wxZ1K。现在我不太确定了-似乎这两个项目都没有得到过多关注。 - Adamski
2
使用BoneCP,是一个非常活跃的、优秀的工具,文档资料齐全且速度非常快。在我们高流量的网站上使用它,从未遇到问题。 - Janning Vygen
2
截至目前,关于c3p0已死的传言似乎大大夸张了:http://sourceforge.net/projects/c3p0/ (最后一次仓库更新是2014年4月4日)。 - Josh Glover
7
一个数据库连接池并不需要大量的功能。一旦它完成并修复了最突出的错误,即使维护者仍然关心它,你也不应该期望太多的活动。 - flup
1
我在2018年仍在使用c3p0连接池。它解决了由于dbcp而引起的问题。 - Mr. Aniket

7

DAO不应该负责获取数据库连接。它们无法知道自己是否作为更大事务的一部分而被使用。您应该将数据源或连接实例传递到DAO中。

如果finally块中的任何一个close调用抛出异常,则其后的所有调用都不会被执行。每个调用都需要在自己的try/catch块中。我将它们放入了一个实用类中作为静态方法。


5
代码看起来没问题,但我会写一个帮助方法来执行关闭操作,否则你将在每个DAO或方法中得到这个冗长的finally块。也许你应该写三个独立的try-catch块来围绕close操作,以确保连接被关闭,无论语句和结果集是否抛出异常。此外,请注意javadoc says

当Statement对象关闭时,如果存在当前ResultSet对象,则也将被关闭。

所以在上面的示例中,你不需要关闭结果集,但你可以这样做。
链接的清理方法是用于关闭数据源的,大多数项目不需要这样做,因为数据源的生命周期与你的应用程序运行的时间一样长。

0

我使用Play框架和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

第三步,然后您需要创建实例。

val cpds = new ComboPooledDataSource()
cpds.setDriverClass(...)
cpds.setJdbcUrl(...)
cpds.setUser(...)
cpds.setPassword(...)

步骤4. 获取连接

cpds.getConnection

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接