背景: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 不是很受欢迎,因为该约束提供了出色的保护,可以防止可能允许保存不一致数据的令人讨厌的应用程序错误。我们选择了选项 1。
ALTER TABLE bond_payments ADD
CONSTRAINT bond_payment_uk UNIQUE (bond_number, payment_id)
DEFERRABLE INITIALLY DEFERRED;
不利的一面是,为监管此约束而创建的索引现在是非唯一索引,因此查询的效率可能会有所降低。我们已经决定这对这个特殊情况没有那么大的损害。另一个缺点(由 Gary 建议)是它可能会受到特定 Oracle 错误的影响——尽管我相信由于应用程序的工作方式,我们将(至少,大部分)免疫。
我们还应该考虑其他选择吗?