重用语句和结果集是否会释放其先前使用的资源?还是我必须在重用之前明确关闭它们?

2022-09-02 12:52:12

示例代码:

        aStmt = aConn.prepareStatement(aQuery);
        aRset = aStmt.executeQuery(cQuery);

        while (cRset.next()) {
            //stuff to determine value of parm1

            aStmt.setString(1, parm1);                
            aRset = aStmt.executeQuery(); 

            //more stuff
        }

我是否必须在 while 语句中的每个循环之后关闭 aStmt 和 aRset?还是在后续循环中重用它们会释放从前面的循环中使用的内存/资源?


答案 1

结果集和(预准备的)语句的行为在 Java API 中明确记录。我建议您阅读实际文档(和JDBC规范)以获取详细信息。

语句 API 说:

默认情况下,每个对象只能同时打开一个对象。因此,如果一个对象的读取与另一个对象的读取交错,则每个对象必须由不同的对象生成。如果存在打开的语句对象,则 Statement 接口中的所有执行方法都会隐式关闭语句的当前 ResultSet 对象。ResultSetStatementResultSetStatement

(强调我的)。

在特定代码中,当您调用 时,分配给 的旧代码由驱动程序隐式关闭。也就是说,最好自己显式关闭它(或使用Java 7 try-with-resources),以防止您忘记通过循环在最后一次迭代中关闭。aStmt.executeQuery()ResultSetaRsetResultSet

现在到:当您准备语句时(通常,实现可能会有所不同),查询将发送到服务器进行编译。执行时,该特定执行的参数将发送到服务器。调用将导致在服务器上解除分配预准备语句,这显然不是您在此处想要的,因为您希望重新使用具有不同参数值的语句。PreparedStatementclose()aStmt

所以简而言之

  1. 这里从技术上讲,关闭不是必需的(除了最后创建的),但最好明确地执行此操作ResultSetResultSet
  2. 您只应在完成后关闭 。PreparedStatement

使用 try-with-resources 是消除这些问题的部分混淆的一种方法,因为您的代码将在完成操作后自动释放资源(在使用范围结束时):

try (
    ResultSet cRset = cStmt.executeQuery(cQuery);
    PreparedStatement aStmt = aConn.prepareStatement(aQuery);
) {
    while (cRset.next()) {
        //stuff to determine value of parm1

        aStmt.setString(1, parm1);                
        try (ResultSet aRset = aStmt.executeQuery()) {
            //more stuff
        }
    }
}

在这段代码的末尾,所有JDBC资源都被正确关闭(以正确的顺序,即使发生异常等)


答案 2

不可以,您不能关闭循环内部。ResultSetStatementwhile

您必须在循环后关闭它们。

另外,如果您想重用,那么在准备好处理之前,您可能不会关闭它。PreparedStatement

最好的规则是在创建时关闭此类资源所在的同一块。在您的情况下,最好的办法是在捕获 .finallySQLException

例如:

try {
    aStmt = aConn.prepareStatement(aQuery);
    cRset = cStmt.executeQuery(cQuery);

    while (cRset.next()) {
        //stuff to determine value of parm1

        aStmt.setString(1, parm1);
        try {
            aRset = aStmt.executeQuery();
        } finally {
            aRset.close();
        }

        //more stuff
    }
} catch (SQLException ex) {
    // Do error handling
} finally {
    // Close Resultset
}

在 Java 7 中,您可以使用 try with resources。


推荐