据说在使用完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) {};
}
问题是关闭连接是否有效,或者是否会留下一些可用的资源。
使用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%完美的,因为在检查关闭状态和关闭本身之间,有一点空间来改变状态。在最坏的情况下,你很快就会得到警告。-但在长期运行的查询中,它小于状态变化的可能性。我们在“平均”负载(150个同时用户)的生产环境中使用了这个模式,我们没有遇到任何问题——所以从来没有看到警告消息。
使用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%完美的,因为在检查关闭状态和关闭本身之间,有一点空间来改变状态。在最坏的情况下,你很快就会得到警告。-但在长期运行的查询中,它小于状态变化的可能性。我们在“平均”负载(150个同时用户)的生产环境中使用了这个模式,我们没有遇到任何问题——所以从来没有看到警告消息。
我创建了以下方法来创建可重用的One Liner:
public void oneMethodToCloseThemAll(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
if (!resultSet.isClosed()) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
if (!statement.isClosed()) {
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
if (!connection.isClosed()) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
我在父类中使用此代码,它继承给所有发送DB查询的类。我可以在所有查询上使用联机程序,即使我没有resultSet。方法负责按照正确的顺序关闭ResultSet、Statement、Connection。这是我的最终块的样子。
finally {
oneMethodToCloseThemAll(resultSet, preStatement, sqlConnection);
}