Java 使用 C3P0 的 JDBC 连接池

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1458693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 12:29:21  来源:igfitidea点击:

JDBC Connection pooling using C3P0

javadatabasedatabase-connectionconnection-poolingc3p0

提问by jai

Following is my helper class to get DB connection:

以下是我获取数据库连接的助手类:

I've used the C3P0 connection pooling as described 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;
    }
}

in the DAO i'll be writing something like this:

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

    }

Now, my question is should I bother to do any other clean up other than closing the cursors(connection/statement/resultSet/preparedStatement) listed in the finally block.

现在,我的问题是除了关闭 finally 块中列出的游标(connection/statement/resultSet/preparedStatement)之外,我是否应该费心做任何其他清理工作。

What is thiscleanup?? When and where should I do this?

什么是这个清理?我应该在何时何地这样做?

Should you find anything wrong in the above code, please point out.

如果您发现上述代码有任何错误,请指出。

采纳答案by skaffman

With a pooled data source, the connections in the pool are not actually closed, they just get returned to the pool. However, when the application is shut down, those connections to the database should be properly and actually closed, which is where the final cleanup comes in.

对于池化数据源,池中的连接实际上并未关闭,它们只是返回到池中。但是,当应用程序关闭时,那些与数据库的连接应该正确且实际关闭,这就是最终清理的地方。

Incidentally, the c3p0 project is pretty much dead in the water, I recommend you use Apache Commons DBCPinstead, it's still being maintained.

顺便说一句,c3p0 项目几乎已经死了,我建议您改用Apache Commons DBCP,它仍在维护中。

回答by Tim Büthe

The code looks fine to me, but I would write a helper method that does the close operations or you'll get this verbose finally-block in every DAO or method. Maybe you should write three separate try-catch-blocks around the close Operations, to make sure the connection is closed no matter if the statement and resultset have thrown an exection. Also note that the javadoc says

代码对我来说看起来不错,但我会编写一个辅助方法来执行关闭操作,否则您将在每个 DAO 或方法中获得这个冗长的 finally 块。也许您应该围绕关闭操作编写三个单独的 try-catch-blocks,以确保无论语句和结果集是否引发执行,连接都已关闭。另请注意,javadoc 说

When a Statement object is closed, its current ResultSet object, if one exists, is also closed.

当 Statement 对象关闭时,其当前 ResultSet 对象(如果存在)也将关闭。

So you don't need to close the resultset in the above example, but you could.

所以你不需要关闭上面例子中的结果集,但你可以。

The linked cleanup method is for closing the datasource, what isn't needed in most projects because the DS lives as long as your app is running.

链接清理方法用于关闭数据源,这在大多数项目中是不需要的,因为只要您的应用程序运行,DS 就会存在。

回答by duffymo

DAOs should not be responsible for acquiring a connection to the database. They have no way to know when they're being used as part of a larger transaction. You should be passing the data source or connection instance into the DAO.

DAO 不应该负责获取与数据库的连接。他们无法知道自己何时被用作更大交易的一部分。您应该将数据源或连接实例传递到 DAO。

If any of the calls to close in your finally block throw an exception, none of the ones that follow will be called. Each one needs to be in its own try/catch block. I put them into a utility class as static methods.

如果您的 finally 块中的任何关闭调用抛出异常,则不会调用后面的任何调用。每个都需要在自己的 try/catch 块中。我将它们作为静态方法放入实用程序类中。

回答by Haimei

I use Play Framework and Scala, so the following example is in play project.

我使用 Play Framework 和 Scala,所以下面的例子是在 play 项目中。

Step1. configuration

第1步。配置

In build.sbt, if you use mysql/hive as database, you need to add these properties.

在 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"
)

Step2. how to access it? you need to import c3p0 library.

第2步。如何访问它?您需要导入 c3p0 库。

import com.mchange.v2.c3p0.ComboPooledDataSource

Step3. and then you need to create instance.

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

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

Step4. you get a connection

第四步。你得到一个连接

cpds.getConnection