gpt4 book ai didi

java - 无法让 hibernate 通过级联删除已从一对多关系中删除的子实例

转载 作者:行者123 更新时间:2023-12-01 15:05:07 25 4
gpt4 key购买 nike

这里有一个小问题:

比方说,我有两个实体类

class Parent {
Set<Child> children;
}
class Child {
SomethingElse reference;
}

现在映射本质上是:

<class name="Parent" lazy="false">
<set name="children" lazy="false" cascade="all-delete-orphan">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
</class>

(我在这里省略了 id 映射和字段,我使用常规生成的 id)

我本质上需要保持一个干净的数据库,就像当我从父级列表中删除元素然后提交父级时,需要删除相应的已删除子数据库条目。子实例引用了我稍后需要能够删除的其他实体,因此如果子实例保留在数据库中,我无法删除这些引用的对象。

到目前为止我发现的是:如果我要保持 hibernate 的 PersistentCollection 包装器就位,我在下面尝试的任何事情都应该有效。问题是,我的数据库对象经过几层框架,其中包括一个 UI 框架,它使用 bean 属性抽象来调用 setter,以及一个网络通信层,它来回克隆和序列化对象。这两个层在内部都替换了集合实例,从而删除了这些 PersistentCollection 包装器。重写这些不这样做不是一个选择。

也就是说,我尝试了 8 件事但没有成功:

1) 配置关系为cascade="all",使用session.update(parent)。

2)配置关系为cascade="all-delete-orphan",使用session.update(parent)。

3) 配置关系为cascade="all"并使用session.merge(parent)

所有这些都会导致 hibernate 执行“UPDATE CHILD SETparent.id = null WHEREparent.id = ...”。重新加载父实例时,这成功地从父列表中删除了子实例,但子实例仍保留在数据库中,并阻止我删除其他引用的实体。

4-6) 使用配置 1-3,同时另外将父键列定义为非空

这会导致 hibernate 不执行任何操作。我在另一篇文章中读到,使键列非空会导致删除。听起来可能,因为更新为 null 不再是一个选项,但不起作用。如果我从集合中删除子项,提交更改并从数据库重新加载实例,子项将重新出现。

7+8) 父键可为空或非空并不重要,但将关系配置为cascade=all-delete-orphans 并使用session.merge(parent)

这会导致 hibernate 抛出异常“由于删除了 PersistedCollection 包装器,因此拥有的实体实例不再引用具有cascade=“all-delete-orphan”的集合”。

为了解决我的问题,我唯一需要的是 hibernate 来执行选项 1-3 中的查询作为删除而不是更新。我希望我只是无法找到配置映射的选项,以便在没有 PersistentCollection 包装器的情况下删除这些映射,但对我来说,目前似乎没有这样的选项。有谁知道是否有办法配置它?

/编辑:为了澄清,我想要发生的事情的示例:

Parent parent = new Parent();
parent.setChildren(new HashSet<Child>(Arrays.asList(new Child()))));
session.insert(parent)
// this correctly results in (approximately):
// SQL> INSERT INTO PARENT ...
// SQL> INSERT INTO CHILD ...

parent.setChildren(new HashSet<Child>()); // using .clear() is not an option.
session.update(parent);
// this results in:
// SQL> UPDATE CHILD set parent_id = null WHERE parent_id = ${id.of.parent}
// but i need this to result in:
// SQL> DELETE FROM CHILD WHERE parent_id = ${id.of.parent}

最佳答案

好吧,我现在显然已经修复了它。问题是我没有分配空集,而是空集。显然,在 session.merge(updated) 的情况下,hibernate 突然区分了空集合和 null 集合。将cascade="all-delete-orphan"和.merge() 与分配给属性的空集合实例一起使用是可行的,分配null 而不是空集合实例会引发上述异常。无论键列上的可为空性约束如何,这都是相同的。

我不知道这是否被认为是故意行为,因为通常空值的行为与空集合相同。我会看看是否能找到更多相关信息,然后可能会提出错误报告。

更新:问题位于 https://hibernate.atlassian.net/browse/HHH-7726

关于java - 无法让 hibernate 通过级联删除已从一对多关系中删除的子实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13067698/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com