在JPA中删除子级时,保持实体关系同步 [英] Keeping entity relationship in sync when deleting child in JPA

查看:115
本文介绍了在JPA中删除子级时,保持实体关系同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解到,您需要保持具有关联关系的实体同步,即,当您从父级中删除子级时,还应该将在子实体中将父级保留为null的属性.在我的示例中,我具有以下父实体:

I've read that you need to keep entities that have a relationship in sync, i.e. when you remove a child from a parent you should also set the attribute that holds the parent to null in the child entity. In my example I have the following parent entity:

public class Parent {
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Child> children;
}

还有孩子:

public class Child {
    @ManyToOne(optional = false)
    private Parent parent;

    public void setParent(Parent parent) {
        this.parent = parent;
    }
}

从父级删除子级的代码如下(在此示例中,Parent可以在其列表中多次具有相同的Child):

The code for removing a child from the parent is as follows (in this example a Parent can have the same Child in its list multiple times):

public void removeChild(Child child) {
    List<Child> childrenToRemove = this.children.stream()
        .filter(c -> c.equals(child))
        .collect(Collectors.toList());
    childrenToRemove.forEach(child -> child.setParent(null));
    this.children.removeAll(childrenToRemove);
}

我首先在每个子级上将Parent设置为NULL,然后将它们从集合中删除.这样可以使实体保持同步.我还可以做的是将removeChild代码更改为以下内容:

I first set the Parent to NULL on each of the children and then remove them from the collection. This keeps the entities in sync. What I could also do is change the removeChild code to the following:

public void removeChild(Child child) {
    this.children.removeIf(c -> c.equals(child));
}

当然,在这种情况下,这些实体不会保持同步,因为这些Child实体中的每个实体仍然具有对Parent的引用.为了弥补这一点,我可以在Child实体中添加以下内容:

Of course in this case the entities are not kept in sync because each of those Child entities still has a reference to the Parent. To remedy that I could add the following to the Child entity:

@PreRemove
public void preRemove() {
    this.parent = null;
}

我现在的问题是,如果Child实体也保存在其他父实体的列表中,例如实体AnotherParent也会保留Child实体的列表,那么我还应该在上述的@PreRemove方法中添加this.anotherParent = null吗?如果Child与其他实体具有单向关系(即另一侧没有保存Child实体的列表,应该将它们设置为null)怎么办?

My question now is, what if Child entity is also kept in a list of a different parent entity, e.g. the entity AnotherParent which also keeps a list of Child entities, should I then also add this.anotherParent = null to the @PreRemove method defined above? What if Child has unidirectional relationship with other entities (i.e. the other side doesn't keep a list of the Child entities, should they be set to null?).

推荐答案

As explained in this article, you should keep the bidirectional associations in sync so that the entity state transitions can propagate and to avoid hard-to-track bugs in your code.

我现在的问题是,如果子实体也保留在列表的列表中,该怎么办? 不同的父实体,例如实体AnotherParent 保留子实体的列表,然后我还应该添加 上面定义的@PreRemove方法的this.anotherParent = null吗?

My question now is, what if Child entity is also kept in a list of a different parent entity, e.g. the entity AnotherParent which also keeps a list of Child entities, should I then also add this.anotherParent = null to the @PreRemove method defined above?

如果当前正在运行的Persistence cOntext中未加载AnotherParent实体,则不必这样做,因为内存中不存在父级集合.

If the AnotherParent entity is not loaded in the currently running Persistence cOntext, you don't have to do that because the parent-side collection does not exist in memory.

如果Child与其他实体有单向关系怎么办 (即,另一方未保留子实体的列表, 它们设置为null吗?).

What if Child has unidirectional relationship with other entities (i.e. the other side doesn't keep a list of the Child entities, should they be set to null?).

如果不这样做,则会得到ConstraintViolationException,因为单向关联更像是多对多而不是一对多.有关更多详细信息,请查看我的"JPA关系"视频课程.

If you don't do that, you'll get a ConstraintViolationException because unidirectional associations are more like many-to-many than one-to-many. For more details, check out my JPA Relationships video course.

这篇关于在JPA中删除子级时,保持实体关系同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆