我们假设我们有两个实体,A和B. B与A有多对一的关系如下:
@Entity
public class A {
@OneToMany(mappedBy="a_id")
private List<B> children;
}
@Entity
public class B {
private String data;
}
现在,我想删除A对象并将删除级联到其所有子对象(B)。有两种方法可以做到这一点:
1)将cascade=CascadeType.ALL, orphanRemoval=true
添加到OneToMany注释中,让JPA在从数据库中删除A对象之前删除所有子项。
2)保持课程原样,只需让数据库级联删除即可。
使用后面的选项有什么问题吗?它会导致实体管理器保留对已删除对象的引用吗?我选择第二个选项的原因是选项一生成n + 1个SQL查询以进行删除,当对象A包含大量子节点时可能需要较长时间,而选项二只生成一个SQL查询然后继续愉快。有没有&#34;最佳实践&#34;关于这个?
答案 0 :(得分:6)
在EclipseLink中,如果使用@CascadeOnDelete注释,则可以使用两者。 EclipseLink还将为您生成级联DDL。
请参阅, http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade
这可以通过让数据库执行删除来优化删除,还可以通过删除对象来维护缓存和持久性单元。
请注意,orphanRemoval = true还将删除从集合中删除的对象,数据库级联约束将不会为您执行此操作,因此仍然需要在JPA中使用规则。还有一些数据库无法处理删除的关系,因为数据库只能在约束的反方向级联,具有外键的OneToOne或具有连接表的OneToMany不能在数据库上级联。
答案 1 :(得分:5)
我更喜欢数据库。为什么呢?
答案 2 :(得分:1)
This answer提出了一些非常强烈的论据,说明为什么它应该是处理级联的JPA,而不是数据库。
以下是相关引用:
...如果您要在数据库上进行级联,而不是声明它们 Hibernate(针对性能问题)你可以在某些情况下获得 错误。这是因为Hibernate将实体存储在其会话中 缓存,所以它不知道数据库删除的东西 级联。
使用二级缓存时,情况会更糟,因为 这个缓存的寿命比会话长,db-side的这种更改会 对于其他会话是不可见的,因为旧的值存储在此会话中 高速缓存中。