我应该让JPA或数据库级联删除吗?

时间:2011-04-26 08:04:26

标签: sql jpa jpa-2.0 eclipselink cascading-deletes

我们假设我们有两个实体,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;关于这个?

3 个答案:

答案 0 :(得分:6)

在EclipseLink中,如果使用@CascadeOnDelete注释,则可以使用两者。 EclipseLink还将为您生成级联DDL。

请参阅, http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade

这可以通过让数据库执行删除来优化删除,还可以通过删除对象来维护缓存和持久性单元。

请注意,orphanRemoval = true还将删除从集合中删除的对象,数据库级联约束将不会为您执行此操作,因此仍然需要在JPA中使用规则。还有一些数据库无法处理删除的关系,因为数据库只能在约束的反方向级联,具有外键的OneToOne或具有连接表的OneToMany不能在数据库上级联。

答案 1 :(得分:5)

我更喜欢数据库。为什么呢?

  • 数据库执行此操作可能要快得多
  • 数据库应该是保存完整性和关系信息的主要场所。 JPA只是反映了这些信息
  • 如果您使用其他应用程序/平台(即没有JPA)进行连接,您仍然可以级联删除记录,这有助于提高数据完整性

答案 2 :(得分:1)

This answer提出了一些非常强烈的论据,说明为什么它应该是处理级联的JPA,而不是数据库。

以下是相关引用:

  

...如果您要在数据库上进行级联,而不是声明它们   Hibernate(针对性能问题)你可以在某些情况下获得   错误。这是因为Hibernate将实体存储在其会话中   缓存,所以它不知道数据库删除的东西   级联。

     

使用二级缓存时,情况会更糟,因为   这个缓存的寿命比会话长,db-side的这种更改会   对于其他会话是不可见的,因为旧的值存储在此会话中   高速缓存中。