java - 必须单独关闭JDBC结果集和语句,尽管之后Connection已关闭?
据说在使用后关闭所有JDBC资源是一个好习惯。 但是,如果我有以下代码,是否有必要关闭Resultset和Statement?
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) {};
}
问题是连接的关闭是否完成了工作,或者是否使用了一些资源。
Zeemee asked 2019-03-06T06:48:24Z
8个解决方案
168 votes
你所做的是完美和非常好的练习。
我说它的良好做法的原因...例如,如果由于某种原因你使用“原始”类型的数据库池并且你调用connection.close(),连接将返回到池,ResultSet/Statement将永远不会关闭 然后你会遇到很多不同的新问题!
所以你不能总是依靠connection.close()来清理。
我希望这有帮助 :)
Paul answered 2019-03-06T06:48:56Z
98 votes
借助try-with-resources语句,Java 1.7让我们的生活更加轻松。
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,connection也将关闭。
Raúl Salinas-Monteagudo answered 2019-03-06T06:49:34Z
60 votes
来自javadocs:
当一个closeQuietly对象关闭时,它 目前Statements对象,如果一个 存在,也是关闭的。
但是,关闭closeQuietly和Statements关闭底层Connections时,javadocs不是很清楚。它们只是声明关闭连接:
发布此closeQuietly对象 数据库和JDBC资源 马上而不是等待 它们会被自动释放。
在我看来,当你完成它们时,总是明确关闭closeQuietly,Statements和Connections,因为close的实现可能因数据库驱动程序而异。
您可以使用Apache的DBUtils中的方法(例如closeQuietly)为自己节省大量的样板代码。
dogbane answered 2019-03-06T06:50:54Z
31 votes
我现在正在使用Oracle和Java。 在这里我的观点:
您应该明确关闭ResultSet.close();和ResultSet,因为Oracle以前在关闭连接后保持游标保持打开存在问题。 如果不关闭Statement(光标),则会抛出超出最大打开游标的错误。
我想您可能会遇到与您使用的其他数据库相同的问题。
完成后,这是教程Close ResultSet:
完成后关闭ResultSet
完成后立即关闭ResultSet.close();对象 甚至使用ResultSet对象 虽然Statement对象关闭了 ResultSet隐含的对象 关闭,明确关闭ResultSet 给垃圾收集器机会 尽早回忆记忆 因为ResultSet对象可能占用 大量内存取决于查询。
ResultSet.close();
bluish answered 2019-03-06T06:52:24Z
6 votes
如果你想要更紧凑的代码,我建议使用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);
}
baron5 answered 2019-03-06T06:52:56Z
2 votes
用于关闭与JDBC相关的资源的正确且安全的方法(取自如何正确关闭JDBC资源 - 每次):
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();
}
Prasanth Jayachandran answered 2019-03-06T06:53:29Z
-1 votes
使用Java 6表单我认为最好在关闭之前检查它是否已关闭(例如,如果某个连接池在其他线程中逐出连接) - 例如某些网络问题 - 语句和结果集状态可以关闭。 (它经常发生,但我在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%完美,因为在检查关闭状态和关闭本身之间,状态的变化有一点空间。 在最坏的情况下,你会得到一个警告。 - 但它比长期查询中状态更改的可能性要小。 我们在生产中使用这种模式,带有“avarage”负载(150同时用户),我们没有遇到任何问题 - 所以永远不要看到那个警告信息。
Csákány Róbert answered 2019-03-06T06:54:26Z
-2 votes
不,你不需要关闭任何东西,但连接。 根据JDBC规范,关闭任何更高的对象将自动关闭较低的对象。 关闭Connection将关闭连接已创建的任何ResultSet。 关闭任何Statement将关闭由该Statement创建的所有Connection.无论Connection是否可以使用都无关紧要。 即使是poolable连接也必须在返回游泳池之前进行清洁。
当然,您可能在Connection上创建了大量语句的长嵌套循环,然后关闭它们是合适的。 我几乎从不关闭ResultSet但是,当关闭Statement或Connection将关闭它们时似乎过度。
Enerccio answered 2019-03-06T06:55:21Z