java - 在 JPA 中删除子项时保持实体关系同步
问题描述
我已经读到您需要使具有关系的实体保持同步,即当您从父级中删除子级时,您还应该在子实体中将保持父级的属性设置为 null。在我的示例中,我有以下父实体:
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;
}
}
从父级中删除子级的代码如下(在此示例中,aParent
可以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);
}
我首先将Parent
每个孩子的 NULL 设置为 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
实体也保存在不同父实体的列表中,例如AnotherParent
也保存实体列表的Child
实体,我是否也应该添加this.anotherParent = null
到@PreRemove
上面定义的方法中?如果Child
与其他实体有单向关系怎么办(即对方不保留Child
实体列表,是否应该将它们设置为空?)。
解决方案
您应该保持双向关联同步,以便实体状态转换可以传播并避免代码中难以跟踪的错误。
我现在的问题是,如果子实体也保存在不同父实体的列表中,例如也保存子实体列表的实体 AnotherParent,我是否应该也将 this.anotherParent = null 添加到定义的 @PreRemove 方法以上?
如果AnotherParent
实体没有加载到当前运行的 Persistence cOntext 中,则不必这样做,因为内存中不存在父端集合。
如果 Child 与其他实体有单向关系怎么办(即对方没有保留 Child 实体的列表,是否应该将它们设置为 null?)。
如果你不这样做,你会得到一个ConstraintViolationException
,因为单向关联更像是多对多而不是一对多。
推荐阅读
- mysql - 如何连接日期并在日期月份下检索
- javascript - 递增 localStorage 对象名称以存储来自输入的数据
- microservices - 事件溯源和 CQRS 如何帮助解耦微服务?
- python - 如何在 Azure Databricks Notebook 中使用 pysft 模块
- git - 使用 TAG 将 Bitbucket 迁移到 Github 以获取现有迁移的存储库
- ios - 在 UITableViewCell 中更新 UITextView 的属性文本时,UITableView 的滚动不流畅
- javascript - 使用javascript替换类在reactjs中不起作用
- algorithm - O(k(logk+deg(H)) 时间算法在二叉树中找到第 k 个最小元素
- angular - 如何从 VS2019 运行 ngServe
- jmeter - Jmeter - 执行带有和不带有计时器的脚本。但结果似乎效果不佳