私は最近、この性質の多くのコードに遭遇しているプロジェクトに移動しました - (これは jdbc postgres ドライバーを使用しています)
try {
Connection conn = pool.getAConnection(); //home-grown conn pool
PreparedStatement ps = ..;
ResultSet rs = ..;
rs = ps.executeQuery();
...
} catch (SQLException se) {
conn.close();
} finally {
if (stmt != null) stmt.close();
if (rs != null) rs.close();
}
どうやらこのコードは、問題を引き起こすことなく、しばらくの間運用されていたようです。
理解しにくいのは、例外フローでは、最初に接続が閉じられるか、プールに返されることです。その後、ステートメントと結果セットを閉じようとします。親接続オブジェクトが閉じられた後にこれを実行するのは理にかなっていますか?
コードの構造上、接続の解放は例外ブロックで行う必要があります。それは変更できません。そうは言っても、接続がプールに解放された後、最後に stmt.close() と rs.close() を残しても大丈夫ですか?
さらに明確にするために、私の理解が正しければ (つまり、ステートメントと結果セットは、接続を閉じる前に閉じる必要があり、後で閉じる必要はありません)、catch と finally の間にいくつかのコードを繰り返す必要があります。改訂されたコードは次のようになります。これは単純化できますか?
try {
...
} catch(Exception ex){
if (rs != null) {
close(rs); rs = null; // close() method impl just calls rs.close() in try-catch block
}
if (ps != null) {
close(ps); ps = null;
}
processException( ex, con); // This method logs and then either closes the connection or releases to pool, depending on some conditions.
con = null;
} finally {
if (rs != null) {
close(rs);
}
if (ps != null) {
close(ps);
}
if (null != con) {
close(con);
}
}
概観のために、このコードはすべて終わっています - 少なくとも 100 ほどのメソッドです! 可能であれば、これをさらに単純化したいと思います。フィードバックをお待ちしております。