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

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


当前回答

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

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

其他回答

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

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

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

完成后关闭ResultSet:

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

据我所知,在当前的JDBC中,resultset和语句实现了AutoCloseable接口。这意味着它们会在被摧毁或超出范围时自动关闭。

使用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个同时用户)的生产环境中使用了这个模式,我们没有遇到任何问题——所以从来没有看到警告消息。

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

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

如果你想要更紧凑的代码,我建议使用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);
}