必须将JDBC结果集和语句单独closures,尽pipe之后closures了连接?

据说是使用后closures所有JDBC资源的好习惯。 但是,如果我有以下代码,是否有必要closures结果集和语句?

Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = // Retrieve connection stmt = conn.prepareStatement(// Some SQL); rs = stmt.executeQuery(); } catch(Exception e) { // Error Handling } finally { try { if (rs != null) rs.close(); } catch (Exception e) {}; try { if (stmt != null) stmt.close(); } catch (Exception e) {}; try { if (conn != null) conn.close(); } catch (Exception e) {}; } 

问题是closures连接是否完成了这项工作,或者是否有一些资源正在使用。

你所做的是完美的,非常好的做法。

我说它的良好实践的原因…例如,如果由于某种原因,您正在使用“原始”types的数据库池,并调用connection.close() ,连接将返回到池和ResultSet / Statement永远不会被closures,然后你会遇到很多不同的新问题!

所以你不能总是依靠connection.close()来清理。

我希望这有帮助 :)

Java 1.7让我们的生活更加简单,这要归功于try-with-resources声明 。

 try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) { try (ResultSet resultSet = statement.executeQuery("some query")) { // Do stuff with the result set. } try (ResultSet resultSet = statement.executeQuery("some query")) { // Do more stuff with the second result set. } } 

这个语法非常简短而优雅。 即使statement不能被创build, connection也将被closures。

从javadocs :

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

但是,在closures底层Connection时,javadoc并不清楚StatementResultSet是否closures。 他们只是说,closures连接:

立即释放此Connection对象的数据库和JDBC资源,而不是等待它们自动释放。

在我看来,总是显式地closuresResultSetsStatementsConnections ,因为close的实现可能因数据库驱动程序而异。

通过使用来自Apache的closeQuietly中的closeQuietly方法,您可以节省大量的锅炉代码。

我现在正在使用Oracle和Java。 在这里我的观点是:

您应该明确地closuresResultSetStatement因为即使在closures连接之后,Oracle在保持游标打开状态方面也存在问题。 如果你不closuresResultSet (游标),它将会抛出一个错误,如超过最大打开游标数

我想你可能遇到与你使用的其他数据库相同的问题。

这里是closures结果集教程完成后 :

完成后closuresResultSet

即使Statement对象在closures时隐式closuresResultSet对象,只要ResultSet对象处理完毕,就closuresResultSet对象,closuresResultSet显然给予垃圾回收器尽可能早地重新记忆内存的机会,因为ResultSet对象可能占用很多内存,具体取决于查询。

ResultSet.close();

如果你想要更简洁的代码,我build议使用Apache Commons DbUtils 。 在这种情况下:

 Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = // Retrieve connection stmt = conn.prepareStatement(// Some SQL); rs = stmt.executeQuery(); } catch(Exception e) { // Error Handling } finally { DbUtils.closeQuietly(rs); DbUtils.closeQuietly(stmt); DbUtils.closeQuietly(conn); } 

closures与JDBC相关的资源的正确和安全的方法(取自如何正确closuresJDBC资源 – 每次 ):

 Connection connection = dataSource.getConnection(); try { Statement statement = connection.createStatement(); try { ResultSet resultSet = statement.executeQuery("some query"); try { // Do stuff with the result set. } finally { resultSet.close(); } } finally { statement.close(); } } finally { connection.close(); } 

对于Java 6格式,我认为最好在closures之前检查它是否closures(例如,如果某个连接池会将其他线程中的连接逐出) – 例如某些networking问题 – 语句和结果集状态可能会closures。 (这不是经常发生,但是我有这个与Oracle和DBCP的问题)。 我的模式是(在旧的Java语法)是:

  try { ... return resp; } finally { if (rs != null && !rs.isClosed()) { try { rs.close(); } catch (Exception e2) { log.warn("Cannot close resultset: " + e2.getMessage()); } } if (stmt != null && !stmt.isClosed()) { try { stmt.close(); } catch (Exception e2) { log.warn("Cannot close statement " + e2.getMessage()); } } if (con != null && !conn.isClosed()) { try { con.close(); } catch (Exception e2) { log.warn("Cannot close connection: " + e2.getMessage()); } } 

从理论上讲,它并不是100%完美的,因为在检查closures状态和closures状态之间,状态的改变是有一点空间的。 在最坏的情况下,你会得到很长的警告。 – 但是它比长期查询中状态改变的可能性要小。 我们在生产过程中使用这种模式,并且我们没有任何问题,所以从来没有看到这个警告信息。