关闭池中的 JDBC 连接

2022-08-31 09:01:50

我们使用JDBC的标准代码部分是...

Connection conn = getConnection(...);
Statement  stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                ResultSet.CONCUR_READ_ONLY);
ResultSet  rset = stmt.executeQuery (sqlQuery);

// do stuff with rset

rset.close(); stmt.close(); conn.close();

问题 1:使用连接池时,是否应在连接结束时关闭连接?如果是这样,池化的目的不是丢失了吗?如果没有,DataSource 如何知道连接的特定实例何时被释放并可以重用?我对这个有点困惑,任何指针都值得赞赏。

问题 2:以下方法是否接近标准?看起来像是尝试从池中获取连接,如果无法建立数据源,请使用老式的 DriverManager。我们甚至不确定在运行时执行哪个部分。重复上面的问题,是否应该关闭从这种方法出来的连接?

synchronized public Connection getConnection (boolean pooledConnection)
                                                        throws SQLException {
        if (pooledConnection) {
                if (ds == null) {
                        try {
                                Context envCtx = (Context)
                                        new InitialContext().lookup("java:comp/env");
                                ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
                                return ds.getConnection();
                        } catch (NamingException e) {
                                e.printStackTrace();
                }}
                return (ds == null) ? getConnection (false) : ds.getConnection();
        }
        return DriverManager.getConnection(
                "jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}

编辑:我认为我们正在获取池连接,因为我们没有看到堆栈跟踪。


答案 1

使用连接池时,是否应在连接结束时关闭连接?如果是这样,池化的目的不是丢失了吗?如果没有,DataSource 如何知道连接的特定实例何时被释放并可以重用?我对这个有点困惑,任何指针都值得赞赏。

是的,当然,您还需要关闭池连接。它实际上是围绕实际连接的包装器。它将在盖子下将实际连接释放回池。由池进一步决定实际连接是否实际关闭或重新用于新调用。因此,无论您是否使用连接池,您都应该始终在获取 JDBC 资源的块的块中以相反的顺序关闭所有 JDBC 资源。在 Java 7 中,这可以通过使用 try-with-resources 语句进一步简化。getConnection()finallytry


以下方法是否接近标准?看起来像是尝试从池中获取连接,如果无法建立数据源,请使用老式的 DriverManager。我们甚至不确定在运行时执行哪个部分。重复上面的问题,是否应该关闭从这种方法出来的连接?

这个例子非常可怕。您只需要在应用程序启动期间在应用程序范围的数据库配置类的某些构造函数/初始化中查找/初始化一次。然后,只需在应用程序生存期的剩余时间内调用同一个数据源即可。无需同步,也无需空值检查。DataSourcegetConnection()

另请参阅:


答案 2

池通常会返回一个包装的 Connection 对象,其中 closed() 方法将被覆盖,通常将 Connection 返回到池。调用 close() 是可以的,可能仍然需要。

close() 方法可能如下所示:

public void close() throws SQLException {
  pool.returnConnection(this);
}

对于第二个问题,您可以添加一个记录器来显示底部块是否曾经运行过。我想,尽管您只需要一种或另一种方式来配置数据库连接。我们仅使用池来访问我们的数据库。无论哪种方式,关闭连接对于防止泄漏都非常重要。


推荐