サンプルコード:
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を閉じる必要がありますか?または、後続のループでそれらを再利用すると、前のループから使用されていたメモリ/リソースが解放されますか?
結果セットと(プリペアド)ステートメントの動作は、Java APIに明示的に文書化されています。詳細については、実際の文書(およびJDBC仕様)を読むことをお勧めします。
Statement
APIによると:
デフォルトでは、
ResultSet
オブジェクトごとに1つのStatement
オブジェクトのみを同時に開くことができます。したがって、あるResultSet
オブジェクトの読み取りが別のオブジェクトの読み取りとインターリーブされている場合、それぞれが異なるStatement
オブジェクトによって生成されている必要があります。Statement
インターフェイスのすべての実行メソッドは、開いているオブジェクトが存在する場合、ステートメントの現在のResultSet
オブジェクトを暗黙的に閉じます。
(私の強調)。
特定のコードでは、aStmt.executeQuery()
を呼び出すと、ResultSet
に割り当てられた古いaRset
がドライバーによって暗黙的に閉じられます。とはいえ、最後にResultSet
を閉じるのを忘れないように、自分で明示的に閉じる(またはJava 7 try-with-resources)を使用する)方がよいでしょう。ループの反復。
PreparedStatement
へ:ステートメントを準備すると(一般に、実装は異なる場合があります)、クエリはコンパイルのためにサーバーに送信されます。実行時に、その特定の実行のパラメーターがサーバーに送信されます。 aStmt
でclose()
を呼び出すと、準備されたステートメントがサーバー上で割り当て解除されます。つまり、明らかに[〜#〜] not [〜#〜] パラメーターに異なる値を使用してステートメントを再利用したいので、ここで必要なもの。
つまり、
ResultSet
を閉じる必要はありませんが(最後に作成されたResultSet
を除く)、明示的に閉じることをお勧めします。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リソースが正しく閉じられます(例外が発生した場合などでも、正しい順序で)
いいえ、ResultSet
ループ内でStatement
とwhile
を閉じることはできません。
ループの後でそれらを閉じる必要があります。
また、PreparedStatement
を再利用する場合は、処理の準備が整うまで閉じないでください。
最善のルールは、そのようなリソースが作成されたのと同じブロックで閉じることです。あなたの場合、最善の方法は、finally
をキャッチした後、SQLException
ブロック内のリソースを閉じることです。
例えば。
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を使用できます。
PreparedStatement API:SQLステートメントはプリコンパイルされ、PreparedStatementオブジェクトに格納されます。次に、このオブジェクトを使用して、このステートメントを複数回効率的に実行できます。
ただし、ResultSetオブジェクトを再利用することはできません。 2回目に新しいResultSetが作成されたときにPreparedStatementオブジェクトでexecuteQueryを呼び出すときに、前のResultSetを閉じないと、リソースリークが発生するリスクがあります。