必须将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并不清楚Statement
和ResultSet
是否closures。 他们只是说,closures连接:
立即释放此
Connection
对象的数据库和JDBC资源,而不是等待它们自动释放。
在我看来,总是显式地closuresResultSets
, Statements
和Connections
,因为close
的实现可能因数据库驱动程序而异。
通过使用来自Apache的closeQuietly
中的closeQuietly方法,您可以节省大量的锅炉代码。
我现在正在使用Oracle和Java。 在这里我的观点是:
您应该明确地closuresResultSet
和Statement
因为即使在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状态之间,状态的改变是有一点空间的。 在最坏的情况下,你会得到很长的警告。 – 但是它比长期查询中状态改变的可能性要小。 我们在生产过程中使用这种模式,并且我们没有任何问题,所以从来没有看到这个警告信息。