栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在合并具有与orphanRemoval设置为true的实体关联的实体时,防止Hibernate删除孤立的实体

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在合并具有与orphanRemoval设置为true的实体关联的实体时,防止Hibernate删除孤立的实体

首先,让我们将原始代码更改为更简单的形式:

StateTable oldState = entityManager.find(StateTable.class, stateTable.getStateId());Country oldCountry = oldState.getCountry();oldState.getCountry().hashCode(); // DELETE is issued, if removed.Country newCountry = entityManager.find(Country.class, stateTable.getCountry().getCountryId());stateTable.setCountry(newCountry);if (ObjectUtils.notEquals(newCountry, oldCountry)) {    oldCountry.remove(oldState);    newCountry.add(stateTable);}entityManager.merge(stateTable);

注意,我仅

oldState.getCountry().hashCode()
在第三行中添加了内容。现在,您可以通过仅删除此行来重现问题。

在我们解释这里发生的事情之前,首先请摘录JPA
2.1规范的
一些摘录。

3.2.4 节:

应用于实体X的刷新操作的语义如下:

  • 如果X是受管实体,则将其同步到数据库。
    • 对于由X的关系引用的所有实体Y,如果已使用级联元素值Cascade = PERSIST或Cascade =
      ALL注释了与Y的关系,则对Y应用持久性操作


3.2.2 节:

应用于实体X的persist操作的语义如下:

  • 如果X是已删除的实体,则它将被管理。

orphanRemoval
JPA
javadoc:

(可选)是否 将删除操作 应用于已从关系中删除的实体,以及是否将删除操作应用于这些实体。

正如我们所看到的,它

orphanRemoval
是根据
remove
操作定义的,因此所有适用的规则也
remove
必须
适用
orphanRemoval

其次,如该答案所述,Hibernate执行的更新顺序是在持久性上下文中加载实体的顺序。更准确地说,更新实体意味着将其当前状态(脏检查)与数据库同步,并将

PERSIST
操作级联到其关联。

现在,这就是您的情况。在事务结束时,Hibernate将持久性上下文与数据库同步。我们有两种情况:

  1. 当出现多余的行(

    hashCode
    )时:

    1. Hibernate
      oldCountry
      与数据库同步。它会在处理之前完成
      newCountry
      ,因为
      oldCountry
      首先已加载(通过调用强制进行代理初始化
      hashCode
      )。
    2. Hibernate看到
      StateTable
      实例已从
      oldCountry
      的集合中删除,因此将该
      StateTable
      实例标记为已删除。
    3. Hibernate
      newCountry
      与数据库同步。该
      PERSIST
      操作级联到,该操作
      stateTableList
      现在包含已删除的
      StateTable
      实体实例。
    4. StateTable
      现在,将再次管理已删除的实例(上面引用的JPA规范的3.2.2节)。
    5. 当多余的行(

      hashCode
      )不存在时:

    6. Hibernate

      newCountry
      与数据库同步。它在处理之前就完成了
      oldCountry
      ,因为
      newCountry
      首先被加载(带有
      entityManager.find
      )。

    7. Hibernate
      oldCountry
      与数据库同步。
    8. Hibernate看到
      StateTable
      实例已从
      oldCountry
      的集合中删除,因此将该
      StateTable
      实例标记为已删除。
    9. StateTable
      实例的删除与数据库同步。

更新的顺序还解释了您的发现,在这些发现中,您基本上

oldCountry
是在
newCountry
从数据库加载之前强制进行了代理初始化。

那么,这是否符合JPA规范?显然可以,没有违反JPA规范规则。

为什么这不便携?

JPA规范(毕竟像其他任何规范一样)使提供者可以自由定义规范未涵盖的许多细节。

另外,这取决于您对“可移植性”的看法。

orphanRemoval
就其正式定义而言,此功能和任何其他JPA功能都是可移植的。但是,这取决于您如何结合使用它们以及JPA提供程序的详细信息。

顺便说一句,规范的 2.9 节建议(但没有明确定义)

orphanRemoval

否则,可移植应用程序不得依赖于特定的删除顺序,并且不得将已孤立的实体重新分配给另一个关系,也不能尝试将其持久化。

但这只是规范中含糊不清或未明确定义的建议的一个示例,因为规范中的其他语句允许持久保留已删除的实体。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/383332.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号