背景: http://jeffkemponoracle.com/2011/03/11/handling-unique-constraint-violations-by-hibernate
私たちのテーブルは次のとおりです。
BOND_PAYMENTS (BOND_PAYMENT_ID, BOND_NUMBER, PAYMENT_ID)
BOND_PAYMENT_ID には主キー制約があり、(BOND_NUMBER, PAYMENT_ID) には一意の制約があります。
アプリケーションは Hibernate を使用し、ユーザーは特定の債券にリンクされたすべての支払いを表示できます。また、新しいリンクを作成したり、既存のリンクを削除したりできます。ページに必要な変更をすべて加えたら、[保存] をクリックすると、Hibernate が魔法のようにデータベースで必要な SQL を実行します。どうやら、Hibernate はどのレコードを削除する必要があるか、どのレコードを挿入する必要があるかを判断し、残りはそのままにしておきます。残念ながら、最初に INSERT を実行し、次に DELETE を実行します。
ユーザーが支払いへのリンクを削除し、気が変わって同じ支払いへのリンクを再挿入した場合、Hibernate は喜んでリンクを挿入してから削除しようとします。これらの挿入/削除は別個の SQL ステートメントとして実行されるため、Oracle は最初の挿入時にすぐに制約を検証し、ORA-00001 一意の制約違反を発行します。
私たちが知っているのは次の 2 つのオプションだけです。
- 制約を延期可能にする
- 一意の制約を削除します
オプション 2 はあまり好ましくありません。これは、制約によって、一貫性のないデータが保存される可能性がある厄介なアプリケーションのバグから優れた保護が提供されるためです。オプション1を使用しました。
ALTER TABLE bond_payments ADD
CONSTRAINT bond_payment_uk UNIQUE (bond_number, payment_id)
DEFERRABLE INITIALLY DEFERRED;
欠点は、この制約をポリシングするために作成されたインデックスが一意ではないインデックスになったため、クエリの効率が多少低下する可能性があることです。これは、この特定のケースではそれほど大きな不利益ではないと判断しました。もう 1 つの欠点 (Gary のアドバイス) は、特定の Oracle バグに悩まされる可能性があることです。ただし、アプリケーションの動作方法により、(少なくとも、ほとんど) 免疫があると思います。
他に考慮すべきオプションはありますか?