17

Connection.close()をスローする可能性がありSqlExceptionますが、私は常に、そのような例外を無視しても安全であると想定してきました (そして、それらを無視しないコードを見たことがありません)。

通常、私は次のように書きます。

 try{
    connection.close();
 }catch(Exception e) {}

または

 try{
    connection.close();
 }catch(Exception e) {
     logger.log(e.getMessage(), e); 
 }

質問は:

  1. それは悪い習慣ですか(そして、そのような例外を無視するときに誰かが問題を抱えていましたか)。
  2. いつConnection.close()例外がスローされますか。
  3. 悪い場合は、例外をどのように処理すればよいですか。

コメント:

例外を破棄するのは悪いことだとわかっていますが、接続を閉じるときにスローされる例外についてのみ言及しています (この場合、これはかなり一般的です)。

誰かがいつConnection.close()何かを投げることができるか知っていますか?

4

12 に答える 12

16

実際、あなたがしていることは(ほぼ)ベストプラクティスです:-)これがSpringのJdbcUtils.javaで見たものです。したがって、別のCatchブロックを追加することをお勧めします。

/**
 * Close the given  ResultSet and ignore any thrown exception.
 * This is useful for typical finally blocks in manual  code.
 * @param resultSet the  ResultSet to close
 * @see javax.resource.cci.ResultSet#close()
 */
private void closeResultSet(ResultSet resultSet) {
  if (resultSet != null) {
    try {
      resultSet.close();
    }
    catch (SQLException ex) {
      logger.debug("Could not close  ResultSet", ex);
    }
    catch (Throwable ex) {
      // We don't trust the  driver: It might throw RuntimeException or Error.
      logger.debug("Unexpected exception on closing  ResultSet", ex);
    }
  }
}
于 2008-10-30T02:52:32.660 に答える
12

一般的に、私は人々がそのような例外を捨てることに無駄な日々を過ごしてきました。

例外を除いて、いくつかの基本的なルールに従うことをお勧めします。

チェックされた例外で問題が発生することは絶対にないと確信している場合は、その例外だけをキャッチし、それを処理する必要がない理由を正確にコメントしてください。(Sleep は、実際に関心がない限り常に無視できる InterruptedException をスローしますが、正直なところ、これは私が通常無視する唯一のケースです。それでも、取得できない場合、ログに記録するコストはいくらですか?)

よくわからないが、たまに発生する可能性がある場合は、スタック トレースをキャッチしてログに記録し、それが問題を引き起こしている場合にそれを見つけられるようにします。繰り返しますが、必要な例外だけをキャッチしてください。

チェックされた例外をスローする方法が見つからない場合は、それをキャッチして、チェックされていない例外として再スローします。

例外の原因が正確にわかっている場合は、それをキャッチして正確な理由をログに記録します。この場合、何が原因であるかが明確であれば、スタック トレースは必要ありません (また、例外が発生した場合は、ログに記録しているクラスについて言及することもできます)。あなたはまだlog4jなどを使用していません。

あなたの問題は最後のカテゴリに分類されるようです.この種のキャッチでは、あなたが書いたものを決して実行せず(例外e)、チェックされていない例外がスローされた場合に備えて、常に特定の例外を実行します(不正なパラメータ、nullポインタ、 ...)

更新:ここでの主な問題は、チェック済み例外が良くないことです。それらが存在する唯一の高度に使用されている言語は Java です。それらは理論的にはきちんとしていますが、実際には、チェックされていない例外では得られないキャッチアンドハイドの動作を引き起こします。

たまには隠してもいいって言ったのに、たくさんの人がコメントしてくれました。具体的には、私が考えることができる1つのケースは次のとおりです。

try {
    Thread.sleep(1000);
catch (InterruptedException e) {
    // I really don't care if this sleep is interrupted!
}

この使用が問題ないと私が感じる主な理由は、この InterruptedException の使用がそもそもチェック済み例外パターンの悪用であり、例外状態を示すよりもスリープの結果を伝えているためだと思います。

次のようにすると、はるかに理にかなっています。

boolean interrupted=Thread.sleep(1000);

しかし、Java を最初に作成したとき、彼らは新しいチェック済み例外パターンを非常に誇りに思っていました (当然のことながら、これは概念的には非常に優れたものであり、実際には失敗するだけです)。

これが許容される別のケースは想像できないので、例外を無視することが有効である可能性がある単一のケースとしてこれをリストする必要があったかもしれません。

于 2008-10-29T19:49:45.383 に答える
6

少なくとも、キャッチしていて対処していない例外は常に常にログ に記録してください。

ごくわずかなのぞき見もせずに飲み込まれて黙ってキャッチされた例外は最悪です。

于 2008-10-30T00:32:27.387 に答える
3

個人的には、少なくともエラーをログに記録するという 2 番目のアイデアが気に入っています。例外をキャッチしているため、理論的には SQL 例外以外のものをキャッチすることは可能です。何が起こるか、またはどれだけまれか (メモリ不足の例外など) はわかりませんが、すべてのエラーを抑制することは私には正しくないようです。

エラーを抑制したい場合は、そのように処理する必要があることがわかっている非常に特定のエラーに対してのみ行います。

仮定の状況: SQL に開いているトランザクションがあり、接続を閉じるとそのために exceptionino が発生した場合、そのエラーを抑制しますか? SQLExceptions を抑制することでさえ、少し危険な場合があります。

于 2008-10-29T19:51:08.733 に答える
1

RuntimeExceptionをスローすることもできます。

try {
    connection.close();
 } catch(Exception e) {
     throw new RuntimeException(e); 
 }

メソッドのシグネチャを変更する必要はなく、後でException.getCauseメソッドを使用して問題の原因を見つけることができます。

于 2008-10-30T01:39:10.700 に答える
1

理想的な世界では、例外が発生しても何もしないでください。もちろん、理想的な世界では、例外が発生することもありません 8-)

したがって、さまざまなオプションの影響を調べる必要があります。

ログのみ: データベース操作はすべて終了し、リソースをクリーンアップする以外に何もすることはありません。この時点で例外が発生した場合、実行される作業に影響を与えない可能性が高いため、エラーをログに記録するだけで十分です。もちろん、ロギング中にエラーが発生した場合は、基本的に、実際には失敗していない失敗したデータベース操作を処理する必要があります。

空のハンドラー: データベース操作はすべて終了しました。リソースをクリーンアップする以外に何もする必要はありません。この時点で例外が発生しても、実行される作業に影響を与えない可能性が高いため、メソッドは正常に戻ります。次のデータベース アクセスで同じ問題が発生する可能性がありますが、トランザクションの開始時に発生するはずです。トランザクションは正しく失敗し、適切に処理されます。問題が解決した場合は、問題が発生したという兆候はありません。

close() 操作を finally ブロックに配置して、確実にクリーンアップが行われるようにすることは、非常に典型的なシナリオです。これは、リソースのクリーンアップを阻害する他のエラーが発生しないようにするためです。エラーが発生しなかった場合、操作が正常に完了したときにメソッドが失敗することはありません。この場合、空の例外処理はごく普通のことです。

もちろん意見は様々でしょう。

于 2008-10-29T21:03:02.817 に答える
1

例外を処理する必要があります。それは悪い習慣ではありません。データベース接続を閉じる直前にネットワークを失ったと想像してください。おそらく例外がスローされます。

珍しいですか?はい。それが例外と呼ばれるものであり、それを無視する理由ではないと思います。失敗する可能性がある場合は、失敗することを忘れないでください。

また、この時点で null 接続が可能かどうか (NullPointerException が発生する可能性があるかどうか) についても検討する必要があります。

if (connection != null) {
   try { 
      connection.close(); 
   } catch (SQLException sqle) { 
      logger.log(e.getMessage(), e); 
   }
}
于 2008-10-29T20:02:20.723 に答える
0

私の経験から、例外を無視することは決して良い考えではありません。私を信じてください、あなたが例外を記録したならば、生産サポートエンジニアとアナリストはあなたにトンに感謝します。

また、適切なロギングフレームワークを使用している場合、例外によるパフォーマンスへの影響はゼロまたは最小限に抑えられます。

于 2008-10-29T20:07:59.370 に答える
0

これが「発生しないエラー」の場合は、例外を再スローして、誰もキャッチしないことを願っています。
これが他のケースである場合、おそらくログに記録します

于 2008-10-30T01:21:55.447 に答える
0

処理できる場合は、処理してください (予期しない場合はログに記録してください)。処理できない場合は、適切に再スローして、上記のコードで処理できるようにします。

黙って例外を飲み込むことは、その人がコードを修正するための重要な情報を除外することになります。

于 2010-04-04T10:04:58.343 に答える
0

データベースへの接続を閉じるときに例外を処理することをお勧めします。コード内のある時点で、ステートメントまたは結果セット オブジェクトにアクセスしようとすると、自動的に例外が発生するためです。したがって、例外を処理することをお勧めします。

于 2012-09-22T13:16:37.573 に答える