3

私たちのコードでは、通常、次のパターンを使用します。

Connection conn;
try{
    conn = getConnection();
    //Do databasey stuff
}catch(Exceptions that get thrown){
}finally{
    try{
        conn.close();
    }catch(SQLException ex){
        logger.error("Failed to cleanup database connection",ex);
    }
}

ただし、findbugs はこれを好みません。conn.close() は例外をスローする可能性があるため、接続が閉じられる保証はありません。findbugs があまりにも衒学的であるか、またはデータベース接続を閉じるためのより良い方法があります。

編集: try catch を close から削除しました。

4

6 に答える 6

6

あなたが本当にやりたいことは、「The Elite Gentleman」の回答を@edu.umd.cs.findbugs.annotations.SuppressWarnings( "OBL_UNSATISFIED_OBLIGATION" )注釈と組み合わせることです。FindBugs は、次の方法でメソッドを完全に閉じる場合にのみ満足しているようです (これは、そうするための好ましいシーケンスです):

...
}finally{
    try{ 
       resultSet.close();
    }catch( SqlException e ){
       //log error
    }finally{
       try{
          statement.close();
       }catch( SqlException e ){
          //log error
       }finally{
          try{
              connection.close();
          }catch( SqlException e ){
              //log error
          }
       }
    }
}

これは非常に冗長であり、手根管の愛以外の理由がない場合は、おそらくやりたくないので、DBUtils.closeQuietly()メソッドを使用する必要があります (または独自の呼び出しを作成します)。ただし、FindBugs はこれを (つまり、ライブラリまたは独自のメソッドを使用して) リソースを適切に閉じていると認識せず、警告を出します。この場合、明らかに偽陽性です。したがって、それが唯一の警告であることを確認してから、そのメソッドの特定の警告を無効にする必要があります。

@edu.umd.cs.findbugs.annotations.SuppressWarnings( "OBL_UNSATISFIED_OBLIGATION" )
public void doStuff( final Connection connection ){
    try{
        //Do databasey stuff
    }catch( SqlException e ){
        //throw a glorious exception....
    }finally{
        DbUtils.closeQuietly( resultSet  );
        DbUtils.closeQuietly( statement  );
        DbUtils.closeQuietly( connection );
}

このようにして、数行のコードでリソースをクリーンアップし、FindBugs 警告を回避します。

于 2011-08-18T14:26:47.077 に答える
6

@duffymo が言及したことを実行するユーティリティが既にあります。Apache のDbUtilsです。

  • DbUtils.close(ResultSet);
  • DbUtils.close(Statement);
  • DbUtils.close(Connection);

APIDocsには、使用可能なすべてのメソッドが表示されます。


アップデート

次に例を示します。

import org.apache.commons.dbutils;


Connection conn;
try{
    conn = getConnection();
    //Do databasey stuff
} catch(Exception e){
    //throw a glorious exception....
} finally{
    DbUtils.closeQuietly(conn); //This hides the SQLException thrown by conn.close();
    //or 
    //DbUtils.close(conn);
}

更新: ArtB で提案されているように、最終的にリソースと接続を閉じて、findBugs がナガーになっている場合は、次の注釈を (メソッドの上に) 追加できます。

@edu.umd.cs.findbugs.annotations.SuppressWarnings("OBL_UNSATISFIED_OBLIGATION")
于 2010-12-09T12:59:37.327 に答える
4

はい、もっと良い方法があります。

クローズを try/catch でラップする静的メソッドを作成します。

public class DatabaseUtils
{
    public static void close(Connection c)
    {
        try
        {
            if (c != null)
            {
                c.close();
            }
        }
        catch (SQLException e)
        {
            // print or log stack trace
        }
    }

    // same for Statement and ResultSet
}
于 2010-12-09T12:54:50.510 に答える
1

はい、クローズを try ブロックにカプセル化する必要がありますが、より賢い方法があります。

try {
    Connection c = getConnection();
    try {
        //do stuff
    } finally {
        c.close();
    }
} catch (SQLException e) {
    //Catch exceptions
}
于 2010-12-09T13:03:20.053 に答える
0

Spring JDBCTemplate のようなものを使用することで、すべてを回避できます。Spring JDBCTemplate は、すべてのオープン/クローズ ロジックを適切にカプセル化し、コードを簡素化し、コードをよりクリーンで読みやすくします (正しい可能性も高くなります)。

テーブルからキーと値のペアのリストにいくつかの列を読み取る例 (ええ、見苦しいですが、理解しやすいです):

        List<Map<String, Object>> resultList = jdbcTemplate.query(query,
                new RowMapper<Map<String, Object>>() {
                    @Override
                    public Map<String, Object> mapRow(ResultSet rs,
                            int rownum) throws SQLException {
                        Map<String, Object> row = new HashMap<String, Object>();
                        int colIndex = 0;
                        row.put(CONTENTID_KEY, rs.getInt(++colIndex));
                        row.put(CONTENTTYPEID_KEY, rs.getInt(++colIndex));
                        row.put(DESCRIPTION_KEY, rs.getString(++colIndex));
                        row.put(CODE_KEY, rs.getString(++colIndex));
                        return row;
                    }
                });

例外処理については、spring jdbcTemplate how to catch exception? を参照してください。

于 2013-05-14T14:45:13.393 に答える
0

これより良い方法はありませんが、確実にすべてをキャッチしたい場合は、パターンを次のように変更します。

Connection conn;
try{
    conn = getConnection();
    //Do databasey stuff
}catch(Exceptions that get thrown){
}finally{
    try {
       conn.close();
    }
    catch  (SQLException se) {
       log.error("database problems...");
       // do more stuff if you need to
    }
}
于 2010-12-09T12:55:17.997 に答える