5

行为不明确和/或危险的休眠映射问题。我有一个一对多的关系,它有一个级联删除孤儿条件和一个 where 条件来限制集合中的项目。在这里映射 -

<hibernate-mapping>
 <class name="User" table="user" > 

  <!-- properties and id ... -->

   <set table="email" inverse="true" cascade="all,delete-orphan" where="deleted!=true">
      <key column="user_id">
      <one-to-many class="Email"/>
   </set>

 </class>
</hibernate-mapping>

现在假设我有一个用户对象,它与一个或多个电子邮件对象相关联,其中至少一个具有已删除属性的“真”值。当我在 User 对象上调用 session.delete() 时,会发生以下哪两种情况?

  1. 删除用户和所有电子邮件对象,包括已删除=true 的对象
  2. 删除的 User 和 Email 对象!=null 将被删除。

一方面,场景 1) 忽略了 where 条件,根据领域模型,这可能是不正确的。但是在场景 2 中)如果父级被删除,并且子(电子邮件)表的连接键上有外键约束,那么删除命令将失败。发生了什么,为什么?这只是 Hibernate 的功能如何模棱两可的另一个例子吗?

4

1 回答 1

4

我没有测试映射,但在我看来,正确的(默认)行为应该是忽略where条件并删除所有子记录(这是删除父项时避免违反 FK 约束的唯一选择)。从商业角度来看,这可能不是“正确的”,但另一个选项也不是“正确的”,因为它不起作用。

总而言之,映射本身看起来不连贯。您不应该级联操作(并手动delete处理子项的删除)。Email

或者,我认为这可能是最正确的行为,您应该实现对 the和 associated的软删除。像这样的东西:UserEmail

<hibernate-mapping>
  <class name="User" table="user" where="deleted<>'1'"> 

    <!-- properties and id ... -->

    <set table="email" inverse="true" cascade="all,delete-orphan" where="deleted<>'1'">
      <key column="user_id">
      <one-to-many class="Email"/>
    </set>
    <sql-delete>UPDATE user SET deleted = '1' WHERE id = ?</sql-delete>
  </class>

  <class name="Email" table="email" where="deleted<>'1'"> 

    <!-- properties and id ... -->

    <sql-delete>UPDATE email SET deleted = '1' WHERE id = ?</sql-delete>
  </class>
</hibernate-mapping>

这里做了什么:

  • sql-delete我们使用更新标志而不是真正的删除(软删除)覆盖默认删除。
  • 我们使用 过滤实体和关联where以仅获取尚未软删除的实体。

这是受到使用 Hibernate 注释的软删除的启发。虽然没有测试。

参考

于 2010-08-12T22:12:26.557 回答