web-dev-qa-db-ja.com

SQLExceptionがチェック例外である理由

SQLExceptionchecked例外である合理的な理由を誰かが考えることができますか?

はい、クエリに構文エラーがある可能性があります
はい、接続が切断された可能性があります
はい、許可の問題がある可能性があります
その他、何とか何とか何とか

しかし、実際には100%の時間(本番環境で稼働している場合)であれば、何の問題もありません。

問題がある場合、呼び出し側のコードは回復するために何もできないので、そのためuncheckedにする必要があります。

チェックされていると、おかしな塊が作成されますtry catchは、JDBCを使用するプロジェクトに関与したことがある人なら誰でも証明するように、コード全体でブロックされます。コードの混乱は重要です。

SQLの難解な性質のため、SQLExceptionが発生する無数の理由とその複雑さは、例外が一時的なネットワークの問題によって引き起こされない限り、基本的に回復できないことを意味しますが、同期呼び出しでも、とにかく沈んでしまいますネットワークの問題が解決されるまで無期限に待つことができないため、トランザクションを失敗させる必要があります。

通常、SQLの呼び出しは次のようになります。

try {
    // make some SQL call(s)
} catch {SQLException e) { 
    // log the exception
    return; // and give up
}

そのようなコードは値を追加しません。あなたが回復するためにあなたがすることができる合理的な何もありません。また、ランタイム例外をバブルアップさせることもできます。つまり、SQLExceptionはruntime(チェックされていない)例外である必要があります。

21
Bohemian

実質的に問題のない時間の100%-これは、が何も言わないあなた自身の観察に限定されます他のシステムについて。世界中にはさまざまなボトルネックのあるさまざまなコンピューターシステムがあります。あなたの成功率はほぼ100%です。他ははるかに低いパーセンテージを処理する必要があります。

よくある誤解は、その発生の頻度によるチェック例外の導入/削除を検討することです。チェック例外は通信チャネルとして機能します。ご存知のように、すべてのメソッドにはそのパブリックインターフェイスがあります。このように、メソッドはそれが受け入れる引数とその本体のコードの結果が何であるかを教えてくれます。

現在進行中のメソッドがその約束(たとえば、戻り値)を維持することができなくなった場合、他のメソッドに何か問題があり、期待したことを実行できないことを通知する方法が必要です。しかし、それを行う方法は?返された値が機能しないときにメッセージを送信すると、呼び出し側のメソッドが適切な値とエラーメッセージを区別する機会がほとんどなくなります。言うまでもなく、一部のメソッドには戻り値としてvoidがあります。では、メソッドのインターフェースで定義された約束を守ることができない場合はどうしますか?さて、あなたは例外をスローします(メッセージを送信します)。

ResultSetを予期していて、データベースへの接続が確立されていない場合は、どうすればよいですか?空のResultSetを返しますか?地獄いいえ、これはデータベースが空であることを示しています。 nullを返しますか?まあ、これは問題を委任するだけで、原因の発見は不明確になります。

その空の結果セットを使用して、それを別のデータベースへの別のクエリの一部にし、一貫性を失わせることができます。

SQLExceptionがないと、1つの間違いでもデータの不整合につながる可能性があります。

3
user1930502

例外をキャッチすると、例外的な状態から回復することができますが、他のことも可能になります。

実行時に問題を修正するためにできることはほとんどないので、SQLExceptionから回復することはできませんが、実行できる便利なことがいくつかあります。

  • デバッグ情報の例外をログに記録します
  • トランザクションをロールバックする

例外は常により高いレベル(または視点によってはより低いレベル)でログに記録できますが、デバッグ時とコードのレビュー時の両方で、セマンティックな値が失われます。

次のようなことをした場合:

try { ... }
catch(SQLException e) 
{ 
    SomeLogger.log(...);
    rollback();
    throw e;
}

後でこのコードに戻ると、コードを精神的に解析して失敗するかどうかを判断する必要なく、試行中のコードが失敗する可能性があることがすぐにわかります。

あなたができるもう1つのことは、データベースリソースが解放されていることを確認することですが、これがすぐに発生するかどうかはわかりません。

2

1つの理由は、メソッドが行うことの抽象化レベルと一致する例外をメソッドがスローする必要があることです。

したがって、データベースから情報をロードするメソッドは、SQLExceptionではなく、ResourceNotFoundExceptionまたはResourceUnavailableExceptionを発生させる必要があります。

SQLExceptionをチェックすることは、開発者に例外をキャッチさせ、この新しいレベルの抽象化にラップさせる方法です。

この引数は、Effective Java Second Edition by Joshua Bloch(Item 61:Throw exceptions適切な例外をスローする)から引用されたものです)。

1
obourgain

チェック済みと未チェックのジレンマには、いくつかのアプローチがあります。呼び出しコードが例外から回復できるかどうかを確認することは1つの方法ですが、これはSQLExcptionchecked例外である理由を説明していません。

マーティンファウラーが著書「リファクタリング」で提供しているもう1つの方法は、callingまたはcalledメソッドが、例外。

callerメソッドがcalledメソッドを呼び出す前にチェックを実行する必要がある場合(たとえば、引数がnullでないことを確認する)、このチェックが行われていない場合、それは明らかにプログラミングエラーが発生すると、呼び出されたメソッドはチェックされていない例外をスローします。

チェックを行うのがcalledメソッドの責任である場合、このメソッドだけがそのようなチェックを実行する方法を認識できるため、calledメソッドからスローされる例外は- チェック済み

SQLExceptionの場合、このクラスだけが知っていると思います:

  • これはデータベースに依存するため、クエリに構文エラーがあります
  • 接続が切れました
  • 許可の問題があります
1
Adam Siemion