重用Statement和Resultset是否会释放先前使用的资源?或者我必须在重用之前明确关闭它们?

时间:2013-07-12 07:09:44

标签: java jdbc resultset

示例代码:

        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吗?或者在后续循环中重用它们会释放先前循环中使用的内存/资源吗?

3 个答案:

答案 0 :(得分:25)

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

Statement API说:

  

默认情况下,每个ResultSet对象只能同时打开一个Statement个对象。因此,如果一个ResultSet对象的读取与另一个Statement对象的读取交错,则每个对象必须由不同的Statement对象生成。 ResultSet界面中的所有执行方法都会隐式关闭一个规则的当前aStmt.executeQuery()对象(如果存在开放的对象)。

(强调我的)。

在您的特定代码中,当您致电ResultSet时,驱动程序会隐式关闭分配给aRset的旧ResultSet。也就是说,最好自己明确地关闭它(或者使用Java 7 try-with-resources),以防止你忘记在循环的最后一次迭代中关闭PreparedStatement

现在到close():当您准备语句时(通常,实现可能会有所不同),查询将被发送到服务器进行编译。在执行时,将特定执行的参数发送到服务器。在aStmt上调用ResultSet会导致准备好的语句在服务器上被释放,显然你想要的是什么,因为你想要重新使用不同的语句参数的值。

所以简而言之

  1. 此处技术上不需要关闭ResultSet(除了最后创建的PreparedStatement),但最好明确地执行此操作
  2. 只有在完成后才能关闭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 } } }
  3. 使用try-with-resources是消除这些问题的一部分混淆的一种方法,因为您的代码在完成后会自动释放资源(在使用范围的最后):

    {{1}}

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

答案 1 :(得分:2)

不,您可能无法关闭ResultSet循环中的Statementwhile

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

此外,如果您想重复使用PreparedStatement,那么在您准备好处理之前,您可能无法关闭它。

最佳规则是在创建的同一块中关闭这些资源。在您的情况下,最好的办法是在捕获finally后关闭SQLException块中的资源。

E.g。

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。

答案 2 :(得分:0)

PreparedStatement API:预编译SQL语句并将其存储在PreparedStatement对象中。然后,可以使用此对象多次有效地执行此语句。

但是你不能重用ResultSet对象。第二次创建新的ResultSet时,在PreparedStatement对象上调用executeQuery时,如果不关闭以前的ResultSet,则可能会导致资源泄漏。