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

hei*_*man 19 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
        }
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*eel 25

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

StatementAPI说:

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

(强调我的).

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

现在到PreparedStatement:当您准备语句时(通常,实现可能会有所不同),查询将被发送到服务器进行编译.在执行时,将特定执行的参数发送到服务器.调用close()aStmt会导致准备的语句在服务器上被重新分配,这显然不是你想要重新使用的语句与它的参数不同的值,你想要的这里.

所以简而言之

  1. ResultSet在这里技术上不需要关闭(除了最后ResultSet创建的),但最好明确地进行
  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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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