我有以下问题时,试图更新我的实体:

"A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance".

我有一个父实体,它有一个Set<…>的子实体。当我尝试更新它时,我得到了要设置到这个集合的所有引用并设置它。

下面的代码表示我的映射:

@OneToMany(mappedBy = "parentEntity", fetch = FetchType.EAGER)
@Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN })
public Set<ChildEntity> getChildren() {
    return this.children;
}

我已经尝试清理Set<..只有>,根据这个:如何“可能”解决问题,但它没有工作。

如果你有什么想法,请告诉我。

谢谢!


当前回答

我唯一一次得到这个错误是当我试图将NULL传递到集合的setter时。为了防止这种情况,我的setter是这样的:

public void setSubmittedForms(Set<SubmittedFormEntity> submittedForms) {
    if(submittedForms == null) {
        this.submittedForms.clear();
    }
    else {
        this.submittedForms = submittedForms;
    }
}

其他回答

检查所有你给sonEntities赋值的地方。您所引用的链接明确指出了创建一个新的HashSet,但您在重新分配该集合时可能会遇到此错误。例如:

public void setChildren(Set<SonEntity> aSet)
{
    this.sonEntities = aSet; //This will override the set that Hibernate is tracking.
}

通常在构造函数中只需要“新建”一次集合。每当您想要向列表中添加或删除一些内容时,您都必须修改列表的内容,而不是分配一个新的列表。

添加子代:

public void addChild(SonEntity aSon)
{
    this.sonEntities.add(aSon);
}

移除儿童:

public void removeChild(SonEntity aSon)
{
    this.sonEntities.remove(aSon);
}

实际上,我的问题是关于实体的equals和hashcode。遗留代码会带来很多问题,永远不要忘记检查它。我所做的只是保持删除孤立策略和正确的等号和hashcode。

具有关系类型:


当集合在hasMany中声明时,不要尝试实例化它,只需添加和删除对象。

class Parent {
    static hasMany = [childs:Child]
}

使用关系类型:


但是集合只有在声明为属性(使用关系)并且没有在声明中初始化时才可能为空。

class Parent {
    List<Child> childs = []
}

我也犯了同样的错误。我的问题是,保存实体后映射的集合仍然为空,当试图更新实体时抛出异常。对我有帮助的是:保存实体,然后进行刷新(集合不再为空),然后执行更新。也许用new ArrayList()来初始化集合也会有帮助。

我的Spring Boot完全不同! 对我来说,这不是由于设置收集属性。

在我的测试中,我试图创建一个实体,并为另一个未使用的集合得到这个错误!

经过这么多的尝试,我只是在测试方法上添加了一个@Transactional,它解决了这个问题。但不要忘记原因。