保存父实体的新实例时如何删除与孤儿相关的实体?

时间:2018-09-21 18:31:34

标签: hibernate jpa kotlin

我试图在使用Hibernate的现有系统中使用不可变属性的Kotlin-y优势。实体结构是

  • 父母
    • 各种属性
    • 孩子名单
      • 子属性
      • 孙子名单

使用以下代码映射。

为了将它们保持为val,当我们要更新{{1时,我们必须创建ParentChildGrandChild的新实例}}实体并保存。但是,这会导致异常,抱怨会话中存在具有相同标识符的Parent的多个实例。

这可以通过调用Parent从会话缓存中删除所有实体或通过调用clear()将新对象合并到现有的缓存实体中来解决。

但是,尽管进行了所有级联操作和orphanRemoval操作,但这并不会删除不再与Parent关联的Childs或不再与Child关联的GrandChilds。因此,检索“父级”仍会返回应删除的“子级”和“子级”。

例如,对于具有1,2和3的孩子的Parent 99,使用

在Kotlin代码中创建了Parent A的新实例。
merge()

(这是必需的,因为Hibernate需要相关对象的完整实例来创建关系)

应该在保存后删除Child#3。实际上,可以正确更新“父级”和2个更新的“子级”的新值,但不会删除“子级3”。

为此,我能够提出的2种“解决方法”是

1)手动确定哪些现有子级不在更新后的父级中,然后直接通过HQL或使用val updatedParent = Parent(99, "NewName", "NewDesc") val updatedChildren = listOf( Child(1, "NewChildName", "NewChildDesc", updatedParent), Child(2, "NewChild2Name", "NewChild2Desc", updatedParent) ) updatedParent.addAll(updatedChildren) 删除它们,以将其从未更新的父级实体的orphanRemoval=true列表中删除。

2)放弃这些属性的Kotlin不变性,并直接更改缓存的Hibernate对象。

选项1适用于“父母”的直系子孙,但随着对子孙的深入了解,它变得繁琐而复杂。

选项2显然是不可取的,因为它抵消了使用Kotlin的某些好处。

在能够更新现有实体的同时保持Kotlin Hibernate域对象不变性的最佳方法是什么?

children

0 个答案:

没有答案