32

私はしばしば次のような状況に遭遇しました:-

try{ 
     ...
     stmts
     ...
} 
catch(Exception ex) {
     ... 
     stmts
     ... 
} finally {
     connection.close // throws an exception
}

これにはまだ try - catch ブロックが最後に必要です。

これを克服するためのベストプラクティスは何ですか?

4

10 に答える 10

26

このような例外をキャッチしてログに記録するメソッドをSQLUtils含むクラスを作成し、必要に応じて使用します。static closeQuietly

最終的には次のようになります。

public class SQLUtils 
{
  private static Log log = LogFactory.getLog(SQLUtils.class);

  public static void closeQuietly(Connection connection)
  {
    try
    {
      if (connection != null)
      {
        connection.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing connection.", e);
    }
  }

  public static void closeQuietly(Statement statement)
  {
    try
    {
      if (statement!= null)
      {
        statement.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing statement.", e);
    }
  }

  public static void closeQuietly(ResultSet resultSet)
  {
    try
    {
      if (resultSet!= null)
      {
        resultSet.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing result set.", e);
    }
  }
}

そして、クライアントコードは次のようになります。

Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try 
{
  connection = getConnection();
  statement = connection.prepareStatement(...);
  resultSet = statement.executeQuery();

  ...
}
finally
{
  SQLUtils.closeQuietly(resultSet);
  SQLUtils.closeQuietly(statment);
  SQLUtils.closeQuietly(connection);
}

更新: Java 7以降、さまざまなJDBCインターフェースが拡張java.lang.AutoCloseableされ、上記のコードは元の質問に答えますが、JDBC APIに対して直接コードを記述している場合は、次のように構造化できます。

try (
  Connection connection = getConnection();
  PreparedStatement statement = connection.prepareStatement(...);
  ResultSet resultSet = statement.executeQuery()
)
{
  ...
}
于 2009-08-26T16:06:05.597 に答える
12

他の人が述べたように、静的closeQuietlyユーティリティが最適です。追加することの1つ-あなたが世界にいるのではjava.ioなくjava.sql、まさにこの目的のための便利なインターフェースがあります-java.io.Closeable

のすべてのデータ ソースとシンク (java.ioすべてのストリーム、チャネル、ライター、およびリーダー) は、このインターフェイスを実装します。そうすれば、多くのオーバーロードされたバージョンを必要とせずに、同じ「close() の例外」問題に対処する単一のユーティリティを作成できます。

例えば

public class IoUtils {

  public static closeQuietly (Closeable closeable) {
    try {
      closeable.close();
    } catch (IOException logAndContinue) {
      ...
    }
  }

}
于 2009-08-26T17:05:19.770 に答える
10

私は通常、このようにしました:

try {
    try {
        ..
        stmts
        ...
    }
    finally {
       connection.close():
    }
} catch (Exception ex) {
     ..
     stmts
     ..    
}

私は通常、この配管を処理してくれるライブラリを使用していないときにのみこれを使用しました。

Imagist指摘しているように、これは技術的には finally が catch の前に実行されるのと同じではありませんが、解決しようとしていた問題は解決すると思います。

于 2009-08-26T16:06:03.820 に答える
4

Commons-io には、入力および出力ストリーム用の closeQuietly() もあります。いつも使っています。これにより、コードがはるかに読みやすくなります。

于 2009-08-26T16:40:59.507 に答える
2

Java 10 では、次のように記述できます。

public void java10() throws SQLException {
    try (var connection = Connections.openConnection();
         var callableStatement = connection.prepareCall("my_call");
         var resultSet = callableStatement.executeQuery()) {

        while (resultSet.next()) {
            var value = resultSet.getString(1);
            System.out.println(value);
        }
    }
}

Java 7、8、および 9 では、次のように記述できます。

public void java7() throws SQLException {
    try (Connection connection = Connections.openConnection();
         CallableStatement callableStatement = connection.prepareCall("my_call");
         ResultSet resultSet = callableStatement.executeQuery()) {

        while (resultSet.next()) {
            String value = resultSet.getString(1);
            System.out.println(value);
        }
    }
}

Java 6 では、次のすべての行を記述する必要があります。

public void java6() throws SQLException {
    Connection connection = Connections.openConnection();
    try {
        CallableStatement callableStatement = connection.prepareCall("my_call");
        try {
            ResultSet resultSet = callableStatement.executeQuery();
            try {
                while (resultSet.next()) {
                    String value = resultSet.getString(1);
                    System.out.println(value);
                }
            } finally {
                try {
                    resultSet.close();
                } catch (Exception ignored) {
                }
            }
        } finally {
            try {
                callableStatement.close();
            } catch (Exception ignored) {
            }
        }
    } finally {
        try {
            connection.close();
        } catch (Exception ignored) {
        }
    }
}
于 2014-12-10T15:05:06.437 に答える
1

もう一度試してみることを躊躇しないでください...最後に中に入ってください。

于 2009-08-26T16:06:25.440 に答える
0

通常、リソースを閉じるときに発生する例外をログに記録する以上のことはしたくないので、実際には独自の try/catch に入れる必要があります。ただし、これは頻繁に発生する一般的なコードであるため、自分自身を繰り返さないでください。2 つの try/catch 項目が同じメソッドに含まれないように、(Nick Holt が示唆するように) 静的メソッドに close を配置してください。コードを読みやすく、追跡しやすくします。

于 2009-08-26T16:39:12.007 に答える
0

Google Guava ライブラリには便利な Closeables#closeQuitely メソッドもあります - これは任意の Closeable に使用できます

于 2013-03-22T13:45:34.290 に答える
0

try ブロックに続いて finally ブロックを実行し、その後で catch ブロックを実行することはできますか?

于 2014-01-23T18:35:45.327 に答える
-1

覚えておいてください..最終的には常にtryまたはcatchのいずれかで実行されます..

于 2009-08-26T16:26:06.620 に答える