0

私は最近、この性質の多くのコードに遭遇しているプロジェクトに移動しました - (これは 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 ほどのメソッドです! 可能であれば、これをさらに単純化したいと思います。フィードバックをお待ちしております。

4

1 に答える 1

0

ブロック内で接続を解放することは完全に理にかなっていfinallyます。また、ブロック内のStatementandを閉じます。ResultSetfinally

理由は簡単です。実行が成功した場合と例外のシナリオの両方で、Statementandが閉じていることを確認しています。ResultSet接続も同様です。私はfinallyブロックでこのようなことをしただろう

try{

}catch(Exception exe){

}finally{
    if (stmt != null) stmt.close();
    if (rs != null) rs.close();

    //release connection to connection pool

}

また、 aStatementが閉じているとき、その流れResultSetも閉じていると思います。rsに関連付けられている場合はstmt、実行すると閉じられると思いますstmt.close()

于 2012-08-01T02:48:44.337 に答える