6

JDBC オブジェクト (接続、ステートメント、結果セット) を使用したら、それらを閉じることを強くお勧めします。ただし、次のような大量のコードが生成されます。

Connection conn = null;
Statement stm = null;
ResultSet res = null;
try {
  // Obtain connection / statement, get results, whatever...
} catch (SQLException e) {
  // ...
} finally {
  if (res != null) { try { res.close(); } catch (SQLException ignore) {}}
  if (stm != null) { try { stm.close(); } catch (SQLException ignore) {}}
  if (conn != null) { try { conn.close(); } catch (SQLException ignore) {}}
}

ここで、ヘルパー関数を実装して、オブジェクトを閉じるための (繰り返しの) コードの量を減らすことを考えました。オブジェクトを引数として取り、close()リフレクションを使用して、各オブジェクトのメソッドを呼び出そうとします (オブジェクトにそのようなメソッドがある場合)。

public void close(Object... objects) {
  for (Object object : objects) {
    for (Method method : object.getClass().getMethods()) {
      if (method.getName().equals("close")) {
        try {
          method.invoke(object);
        } catch (Exception e) {
          e.printStackTrace();
        }
        break; // break on the methods, go for the next object
      }
    }
  }
}

finallyブロックは次のように縮小できます。

} finally {
  close(res, stm, conn);
}

それは良いことですか?いいえの場合、その理由は何ですか? 「より良い」方法はありますか?

4

4 に答える 4

8

個人的には、リフレクションを必要とせずにこれを行う良い方法がたくさんあるので、この場合はリフレクションを使用しません。ここにあなたができるいくつかのことがあります。

  1. スプリングを使用します。Spring には、JdbcTemplateJdbc コーディングの冗長性を軽減するのに役立つオブジェクトがあります。定型コードは の実装に隠されているJdbcTemplateため、アプリにとって重要なことは自由に行うことができます。
  2. Java7を使用します。Java7 は、インターフェイスを実装するオブジェクトを簡単に閉じることができる新しい言語構造を提供しAutoClosableます。
  3. 定型コードを処理する独自のライブラリを作成します。Spring がニーズに対して重すぎる場合は、Jdbc インタラクション クラスを拡張できる 1 つの基本クラスで、すべてのクローズを簡単に自分で行うことができます。一度書く必要がありますが、ほとんどの場合、目に見えず、頭から離れている可能性があります。

Java7 の方法は次のようになります。

try (
    Connection conn = getConnectionSomehow();
    Statement statement = getStatementFromConnSomehow(conn);
) {
    //use connection
    //use statement
} catch(SomeException ex) {
    //do something with exception
}//hey, check it out, conn and statement will be closed automatically! :)
于 2012-08-17T15:15:04.823 に答える
2

これは、新しい AutoCloseable 機能とインターフェースを備えた Java 7 で修正されています。

java6 でそれを行う必要がある場合は、aspectj を使用して、クローズ コールをラップするための注釈を作成することをお勧めします。

于 2012-08-17T15:15:15.450 に答える
1

Java 7 は必要ありませんし、AOP や Spring も必要ありません (そして、確かにリフレクションは必要ありません)。コードを逆にして、クラスを次のような貧弱なクロージャーとして使用することができます (疑似コード):

public class DbExecutor {
    public static void exec(DbAction action) {
        Connection conn = null;
        try {
            action.consume(conn);
        } catch (SQLException e) {
            // ...
        } finally {
          if (conn != null) { try { conn.close(); } catch (SQLException ignore) {}}
        }

       }
}

public class DbAction {
    public abstract void consume(Connection conn) throws SQLException;

    public static class QueryOne extends DbAction {
        public List<String> myAnswer = new ArrayList<String>();

        @Override
        public abstract void consume(Connection conn) throws SQLException {
            Statement stm = conn.prepare(...);
            ResultSet res = stm.execute();
            while(res.hasNext()) {
                myAnswer.add(...);
            }
            //...
        }
    }

    public static class QueryTwo extends DbAction {...}
}

それを使用するには、次のようにします。

DbAction.QueryOne qAction = new DbAction.QueryOne();
DbExecutor.exec(qAction);
System.out.println("found this many:" + qAction.myAnswer.size());

接続管理から解放され、閉じることを忘れることはありません。また、接続を閉じると自動的に Statement と ResultSet が閉じられます。

匿名の内部クラスも使用できますが、結果を取得することは、この明示的なアプローチよりも問題になる可能性があることに注意してください。

于 2012-08-17T18:41:49.420 に答える
0

conn を閉じるだけで十分ですが、最初に res を閉じ、次に stm を閉じるのが良いコード スタイルです。

于 2012-08-22T13:28:02.007 に答える