问题
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