Hibernate执行的级联删除顺序有误

4
我的数据库出现了一条约束违反(FK)的错误,因为Hibernate在错误的顺序下执行级联删除。
详情:我要删除一个拥有钱包交易(value-type)的会员,而且钱包交易与产品有关联,就像会员包含产品集合一样(请参见下面的Hibernate映射)。
我要删除一个会员实例,并希望Hibernate同时删除产品和钱包交易。它似乎首先通过级联删除删除产品实例,这样就会引发FK违规,因为它仍然被钱包交易引用,而这些交易尚未通过级联删除被删除。
我已经尝试过级联设置,例如all-delete-orphan(在产品上),但没有成功。我还清空了钱包交易并在同一删除事务中刷新了Hibernate会话,但仍然出现了相同的错误。
请帮助我正确排序级联删除的顺序。以下是Hibernate映射(我省略了PK和属性之类的不重要部分):
<class name="Member" table="mem" >
 <component name="wallet" class="Wallet">
  <set name="transactions" table="wallet_tx" cascade="all">
   <cache usage="read-write" />
   <key column="idTaxer" not-null="true" />
   <composite-element class="WalletTransaction">
    <property name="amount" type="big_decimal" column="amount" />
    <many-to-one name="product" column="idPrdInst" class="Product" cascade="none" />
   </composite-element>
  </set>
 </component>

 <set name="products"  cascade="delete" inverse="true">
  <key column="idTaxer" not-null="true" />
  <one-to-many class="Product" />
 </set>
</class>

<class name="Product" table="prd" >
 ...
 <many-to-one name="member" column="idMember" class="Member" cascade="none" />
</class>

数据库错误:

ERROR:  update or delete on table "prd" violates foreign key constraint "fk_1umej7" on table "wallet_tx"
DETAIL:  Key (id)=(75bef42fc4544) is still referenced from table "wallet_tx".

这个问题在这里得到了回答:https://dev59.com/90fSa4cB1Zd3GeqPAt2c - orzech
谢谢orzech,我知道这篇帖子,但它没有解决我的问题。 - edbras
2个回答

1
如果您想要清空钱包交易并期望它被删除,您必须在交易关系上设置delete-orphan。
如果产品仍然首先被删除,您可以在从交易集中移除钱包tx后刷新,这将起作用,但肯定不是最先进的方式。
否则,您可以尝试映射产品 - 交易oneToMany关系,并在其上设置级联删除(带有反向),产品删除将首先触发交易删除。

在XML映射中,"产品-交易oneToMany"映射会是什么样子?我已经尝试了其他选项,但它们都不起作用(在交易上孤儿删除不会改变产品的第一次删除)。谢谢。 - edbras

1

改为:

<set name="transactions" table="wallet_tx" cascade="all">

you should have:

<set name="transactions" table="wallet_tx" cascade="all-delete-orphan">

在删除成员父实体之前,简单清除事务集。


抱歉回复晚了,我一直在忙于解决其他的 bug。目前我似乎无法重现这个问题,有点沮丧 :( 我扩展了单元测试以很好地表示所描述的问题,但没有运气。如果它出现了,我当然会回到这个问题上。目前它使用上述映射工作,而不需要先清空事务集合。在日志中,我注意到它按正确的顺序生成 SQL 查询。顺便说一句:你之前提出的建议我已经尝试过,但当时并没有解决问题。抱歉.. - edbras
问题又出现了,我正在尝试解决它,但没有成功。你的解决方案不起作用,不知道为什么,可能是因为产品到成员有额外的回链,很奇怪... 有什么想法吗? - edbras
但它是可嵌入的,你没有双向关联。 - Vlad Mihalcea
1
我解决了:我将包含的集合设置为null,而不是空集合,导致Hibernate无法再跟踪它。类似于这个问题:https://dev59.com/Am035IYBdhLWcg3wKsua - edbras
@edbras 你应该把这个评论作为答案并接受它。 - Gab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接