19

サンプルコード:

        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 を閉じる必要がありますか? または、後続のループでそれらを再利用すると、前のループで使用されたメモリ/リソースが解放されますか?

4

3 に答える 3

26

結果セットと (準備された) ステートメントの動作は、Java API で明示的に文書化されています。詳細については、実際のドキュメント (および JDBC 仕様) を読むことをお勧めします。

StatementAPI は次のように述べています。

デフォルトでは、ResultSetオブジェクトごとに 1 つのオブジェクトのみStatementを同時に開くことができます。したがって、あるResultSetオブジェクトの読み取りが別のオブジェクトの読み取りとインターリーブされる場合、それぞれが異なるStatementオブジェクトによって生成されたに違いありません。インターフェイス内のすべての実行メソッドは、開いStatementているステートメントの現在のオブジェクトが存在する場合、そのオブジェクトを暗黙的に閉じResultSetます。

(強調鉱山)。

特定のコードでは、 を呼び出すaStmt.executeQuery()と、古いResultSet割り当て先aRsetがドライバーによって暗黙的に閉じられます。とは言ってもResultSet、ループの最後の反復で を閉じるのを忘れないようにするには、自分で明示的に閉じる (または Java 7 の try-with-resources を使用する) 方がよいでしょう。

PreparedStatementステートメントを準備すると (一般に、実装はさまざまです)、クエリがコンパイルのためにサーバーに送信されます。実行時に、その特定の実行のパラメーターがサーバーに送信されます。close()onを呼び出すと、サーバー上で準備されたステートメントの割り当てが解除されます。パラメーターに異なる値を指定してステートメントを再利用する必要があるためaStmt、これは明らかにここで必要なことではありません。

要するに

  1. ここで閉じるResultSetことは技術的には必要ありませんが (最後に作成されたものを除くResultSet)、明示的に行う方がよいでしょう
  2. PreparedStatement作業が完了したときにのみ閉じる必要があります。

try-with-resourcesを使用することは、これらの問題に関する混乱の一部を解消する 1 つの方法です。これは、コードの使用が完了すると (使用範囲の終了時に)、コードが自動的にリソースを解放するためです。

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 リソースが正しく閉じられます (例外が発生した場合でも、正しい順序で)

于 2013-07-12T07:37:48.220 に答える