gpt4 book ai didi

oracle - 强制 Hibernate 在 INSERT 之前发出 DELETE 以避免违反唯一约束?

转载 作者:行者123 更新时间:2023-12-04 15:48:11 24 4
gpt4 key购买 nike

背景: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 错误——尽管我相信我们会(至少,大部分)由于应用程序的工作方式而受到影响。

    还有其他我们应该考虑的选择吗?

    最佳答案

    从你描述的问题看,不清楚你是否有实体BondPayment或者如果您有 Bond直接链接到 Payment .现在,我想你有 Payment 之间的链接和 Bond通过 BondPayment .在这种情况下,Hibernate 正在做正确的事情,您需要在应用程序中添加一些逻辑来检索链接并删除它(或更改它)。像这样的东西:

    bond.getBondPayment().setPayment(newPayment);

    你可能正在做这样的事情:
    BondPayment bondPayment = new BondPayment();
    bondPayment.setPayment(newPayment);
    bondPayment.setBond(bond);
    bond.setBondPayment(bondPayment);

    在第一种情况下, BondPayment.id被保留,而您只是在更改 payment为了它。在第二种情况下,它是一个全新的 BondPayment ,它将与数据库中的现有记录冲突。

    我说 Hibernate 正在做正确的事情,因为它威胁 BondPayment作为“常规”实体,其生命周期由您的应用程序定义。这与拥有 User 相同对 login 具有唯一约束,并且您正尝试插入第二条记录重复 login . Hibernate 会接受(它不知道 login 是否存在于数据库中)并且您的数据库将拒绝。

    关于oracle - 强制 Hibernate 在 INSERT 之前发出 DELETE 以避免违反唯一约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5269256/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com