在 JPA 中删除 child 时保持实体关系同步
Keeping entity relationship in sync when deleting child in JPA
我读到您需要保持具有同步关系的实体,即当您从 parent 中删除 child 时,您还应该设置保存 parent 到 child 实体中的 null。在我的示例中,我有以下 parent 实体:
public class Parent {
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Child> children;
}
和 child:
public class Child {
@ManyToOne(optional = false)
private Parent parent;
public void setParent(Parent parent) {
this.parent = parent;
}
}
从parent中删除child的代码如下(在本例中,Parent
的列表中可以多次包含相同的Child
) :
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);
}
我首先将每个 children 的 Parent
设置为 NULL,然后将它们从集合中删除。这使实体保持同步。我还可以将 removeChild
代码更改为以下内容:
public void removeChild(Child child) {
this.children.removeIf(c -> c.equals(child));
}
当然,在这种情况下,实体不会保持同步,因为每个 Child
实体仍然具有对 Parent
的引用。为了解决这个问题,我可以将以下内容添加到 Child
实体中:
@PreRemove
public void preRemove() {
this.parent = null;
}
我现在的问题是,如果 Child
实体也保存在另一个 parent 实体的列表中,例如实体 AnotherParent
也保留了 Child
实体的列表,那么我是否也应该将 this.anotherParent = null
添加到上面定义的 @PreRemove
方法中?如果 Child
与其他实体有单向关系怎么办(即另一方没有保留 Child
实体的列表,是否应该将它们设置为空?)。
您应该保持双向关联同步,以便实体状态转换可以传播并避免代码中难以跟踪的错误。
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?
如果 AnotherParent
实体未加载到当前 运行 Persistence cOntext 中,则不必执行此操作,因为内存中不存在父端集合。
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
因为单向关联更像是多对多而不是一对多。
我读到您需要保持具有同步关系的实体,即当您从 parent 中删除 child 时,您还应该设置保存 parent 到 child 实体中的 null。在我的示例中,我有以下 parent 实体:
public class Parent {
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Child> children;
}
和 child:
public class Child {
@ManyToOne(optional = false)
private Parent parent;
public void setParent(Parent parent) {
this.parent = parent;
}
}
从parent中删除child的代码如下(在本例中,Parent
的列表中可以多次包含相同的Child
) :
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);
}
我首先将每个 children 的 Parent
设置为 NULL,然后将它们从集合中删除。这使实体保持同步。我还可以将 removeChild
代码更改为以下内容:
public void removeChild(Child child) {
this.children.removeIf(c -> c.equals(child));
}
当然,在这种情况下,实体不会保持同步,因为每个 Child
实体仍然具有对 Parent
的引用。为了解决这个问题,我可以将以下内容添加到 Child
实体中:
@PreRemove
public void preRemove() {
this.parent = null;
}
我现在的问题是,如果 Child
实体也保存在另一个 parent 实体的列表中,例如实体 AnotherParent
也保留了 Child
实体的列表,那么我是否也应该将 this.anotherParent = null
添加到上面定义的 @PreRemove
方法中?如果 Child
与其他实体有单向关系怎么办(即另一方没有保留 Child
实体的列表,是否应该将它们设置为空?)。
您应该保持双向关联同步,以便实体状态转换可以传播并避免代码中难以跟踪的错误。
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?
如果 AnotherParent
实体未加载到当前 运行 Persistence cOntext 中,则不必执行此操作,因为内存中不存在父端集合。
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
因为单向关联更像是多对多而不是一对多。