Keeping entity relationship in sync when deleting child in JPA

允我心安 提交于 2019-12-11 17:36:02

问题


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;
}

And the child:

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

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

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);
}

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));
}

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;
}

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?).


回答1:


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.

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?

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.

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?).

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.



来源:https://stackoverflow.com/questions/51743338/keeping-entity-relationship-in-sync-when-deleting-child-in-jpa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!