据说在使用完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) {};
}

问题是关闭连接是否有效,或者是否会留下一些可用的资源。


当前回答

一些方便功能:

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);
}

其他回答

来自javadocs:

当一个Statement对象被关闭时,它的 当前ResultSet对象,如果有 存在,也是封闭的。

然而,当你关闭底层连接时,javadocs并不清楚Statement和ResultSet是否关闭。它们简单地声明关闭一个连接:

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

在我看来,当你用完ResultSets, Statements和Connections时,总是显式地关闭它们,因为close的实现在不同的数据库驱动程序中是不同的。

通过在Apache的DBUtils中使用closequiet等方法,可以节省大量的模板代码。

正确和安全的关闭与JDBC this相关的资源的方法(摘自如何正确地关闭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();
}

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

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

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

不,您不需要关闭连接以外的任何东西。根据JDBC规范,关闭任何较高的对象都会自动关闭较低的对象。关闭连接将关闭连接所创建的任何语句。关闭任何语句将关闭由该语句创建的所有结果集。连接是否可池并不重要。即使是可入池的连接也必须在返回池之前进行清洁。

当然,您可能在Connection上有很长的嵌套循环,创建了许多语句,然后关闭它们是合适的。虽然我几乎从来没有关闭ResultSet,但关闭语句或连接将关闭它们时似乎过度了。

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

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