我试图在使用Hibernate的现有系统中使用不可变属性的Kotlin-y优势。实体结构是
使用以下代码映射。
为了将它们保持为val
,当我们要更新{{1时,我们必须创建Parent
,Child
和GrandChild
的新实例}}实体并保存。但是,这会导致异常,抱怨会话中存在具有相同标识符的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