据说在使用完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 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.
    }
}

这个语法非常简洁和优雅。即使不能创建语句,连接也会被关闭。

其他回答

我现在使用Oracle和Java。以下是我的观点:

您应该显式地关闭ResultSet和Statement,因为Oracle以前在关闭连接后仍然保持游标打开的问题。如果您不关闭ResultSet(游标),它将抛出一个错误,如超过最大打开游标。

我认为您在使用其他数据库时可能会遇到同样的问题。

完成后关闭ResultSet:

完成时关闭ResultSet 完成后立即关闭ResultSet对象 使用ResultSet对象甚至 对象关闭 ResultSet对象 close,显式关闭ResultSet 给垃圾收集器机会 尽早回忆 因为ResultSet对象可能占用 大量内存取决于查询。 ResultSet.close ();

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

我之所以说这是一种很好的实践……例如,如果由于某种原因,您正在使用“原始”类型的数据库池,并且调用connection.close(),连接将返回到池中,ResultSet/Statement将永远不会关闭,然后您将遇到许多不同的新问题!

所以你不能总是指望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.
    }
}

这个语法非常简洁和优雅。即使不能创建语句,连接也会被关闭。

连接是否可池并不重要。即使是可入池的连接也必须在返回池之前进行清洁。

“干净”通常意味着关闭结果集和回滚任何挂起的事务,但不关闭连接。否则,池化就失去了意义。

一些方便功能:

public static void silentCloseResultSets(Statement st) {
    try {
        while (!(!st.getMoreResults() && (st.getUpdateCount() == -1))) {}
    } catch (SQLException ignore) {}
}
public static void silentCloseResultSets(Statement ...statements) {
    for (Statement st: statements) silentCloseResultSets(st);
}