2009-04-07 6 views
10

データベースに依存しないJavaプログラムがあります。重複したキーのためにSQLExceptionがスローされた場合は、挿入する際に知っておく必要があります。重複のためにSQLExceptionがスローされたかどうかを確認

単一のデータベースドライバを使用していた場合は、単にErrorCodeを使用しますが、非常に異なるエンジンを使用できるため、ErrorCodeは同じではありません。

誰もこれまでに行ったことはありますか?何か案は?

多くのTIA!

編集:ドライバクラス(つまり:org.apache.derby.jdbc.ClientDriver)とその他の必要な情報(ユーザー名、パスワード、URLなど)を保存する設定ファイルがあります。接続は常に "java.SQL.Connection"として渡されるので、どのドライバが使用されているかは本当に気にしません。

+0

コード内のデータにどのようにアクセスしていますか? JDBCを使っているのですか、データベース固有のクラスがありますか? –

+0

ドライバクラスと接続パラメータが格納されている構成ファイルがあります。 – ferro

答えて

7

基本的なJDBCでは、データベース間のやり方であなたが言っていることをする方法はありません。あなたが言及したようにgetErrorCodeを使用することができますが、ベンダー固有のエラーコードが必要です。

私はこれを回避するために見るだけで3つの方法がある:

  1. は、他の誰かがいることを言及し、(Hibernateは、おそらくこれを行うだろう、意味のある例外にエラーコードから翻訳の全てを行うフレームワークのいくつかの並べ替えを使用します
  2. 挿入を実行する前に、重複を手動で選択して選択します。 (これは100%ではありません。なぜなら、技術的に誰かがあなたの質問の後にインサートをした可能性があるからです)。
  3. 挿入にSQL例外が発生したら、そのIDを照会してみてください。一致を実際に見つけることができれば、受け取ったエラーが重複した主キーに起因するものであることをかなり確信することができます。 (複数の問題があった可能性はありますが、それは実際に投げられたものではありませんでした)。

可能な限り問題を避けるためにコードを記述し、必要ならば#3を使用することをおすすめします。

+0

#3は並行性を無視するので、特に良いアドバイスのようには思えません。つまり、他の接続がレコードを削除したり追加したりしたとしても、この関係は完全な無関係の理由で例外を投げたのはどうなのでしょうか?この接続では存在しない行をロックする方法はないので、それがその行為であることを証明することはできません。 (テーブル全体をロックすることはできますが、テーブルへの同時アクセスは最小限に抑えることができます) 実際には、#2と#3の同時実行の問題は同じです。唯一の実行可能なオプションとして#1が残っています。 – MikeB

0

私は簡単で信頼性の高い方法は、挿入を行う前にキーが存在するかどうかを確認することです。あなたが正しく指摘したように、各データベースにはエラーを報告する独自の方法があります。

+0

コード内のデータへのアクセス方法によって異なります。これは質問からはっきりしていないので、私はこれが「唯一の」方法であるとは断言できません。 –

+0

コードでアクセスされているデータが挿入時に重複キーにどのように影響するかはわかりません。しかし、私はこれが唯一の解決策であると主張することはできません。私の答えは修正されました。 – wentbackward

1

例外が発生した理由を伝えるために例外に頼ることができない場合は、「select count(*)from table where key = @keyfailedtoinsert;」という例外を使ってテストできます。

残念ながら、例外として、テーブル名とキー名は保証されません。場合によっては、JDBCドライバと呼ばれるJavaコードでは、ストアドプロシージャを使用して挿入が発生した場合や、トリガのように挿入が発生した場合など、それらを持つことはできません。

したがって、各JDBCドライバのベンダーを信頼する必要があります。

2

既知の重複キーを挿入し、スローされたエラーコードを記録することで、起動時(または設定時)にプログラムを「トレーニング」することができます。

+0

これは、返されたエラーが確かに挿入時の重複キーであることを前提にしています。あなたは、エラーが実際にあなたが期待したものであったことを証明する方法がありません。 – wentbackward

+0

@wentbackward - あなたは90%のケースを取って、接続、選択、テスト、選択 - の直後であると仮定してもよいし、ユーザーにエラーメッセージを読んで確認するように頼んでもよい。それは正確な科学ではありませんが、それは十分に近いでしょう。 –

0

何か不足していますか? JDBCを使用している場合は、使用されているDBに関係なく、重複したキーの例外が戻されます。

または、あなたが挿入を試みる前にダウピーを決定する方法を尋ねましたか?

-1

私はあなたがJDBCを使用していないと仮定している、またはこれは非常に単純なエラーの検索になります。

異なるデータベースにアクセスするためのクラスが異なりますか。その場合は、データベース固有のクラスで例外をキャッチし、すべてのデータベース型で共有される独自の例外タイプをスローすることができます。

2

私は理想的な解決策は、このケースで特定の例外、おそらくSQLExceptionのサブクラスDuplicateKeyExceptionまたは同様の何かをスローするデータ層を持つことだと思う。

異なる例外を異なる方法で処理できるようにするには、まず異なる例外タイプ(またはサブタイプ)をスローする必要があります。 「過渡的例外」、「データの整合性の例外」、彼らは「回復可能な例外」の種類のサブツリーで、DataAccessExceptionを拡張すべてがa very rich hierarchy of "database exceptions"を提供:

私は、これはSpringフレームワークは、物事が本当に正しい取得するエリアだと思いますこれにより、クライアントコードは、処理または処理できる例外タイプ(または何もありません)を自由にキャッチできます。トランザクションを再実行すると再現できない可能性があるエラーを示す例外、回復不可能なエラー、または単にルートタイプをキャッチすることができます。

8

これはまさにSQLException.getSQLState()の目的です。 Googleによると、「23000」は、少なくともMySQLPostgreSQL、およびOracleの唯一の制約違反を示します。

+1

例えばDB2上では同じではない – ferro

+0

Hrm、そうです。いくつのデータベースをサポートする必要がありますか?それは本当に無限の数字ですか?あなたは、各DBのSQLState/ErrorCodeペアが何であるかを理解し、それらをすべて処理する方が良いかもしれません。前回の行を確認するためにSELECTを行うよりもずっと効果的です。 –

+0

DB接続を受け取り、どのドライバが使用されているかを確認するメソッドを作成し、次にgetSQLState()を比較して重複キーがあるかどうかを確認します。 – ferro

関連する問題