2011-04-26 102 views
10

比方说,我们有两个实体,A和B. B有很多一对一关系提升到一个类似如下:我应该让JPA还是数据库级联删除?

@Entity 
public class A { 
    @OneToMany(mappedBy="a_id") 
    private List<B> children; 
} 

@Entity 
public class B { 
    private String data; 
} 

现在,我要删除的目的和级联删除其所有孩子(B)。有两种方法可以做到这一点:

1)将cascade=CascadeType.ALL, orphanRemoval=true添加到OneToMany批注中,让JPA在从数据库中删除A对象之前删除所有的孩子。

2)让类保持原样,只是让数据库级联删除。

使用后面的选项有什么问题吗?它会导致实体管理器保持对已经删除的对象的引用吗?我选择选项二的原因在于,选项一生成n + 1个SQL查询以进行删除操作,当对象A包含大量子项时可能需要很长时间,而选项二只生成一个SQL查询,然后继续愉快。有没有关于这方面的“最佳做法”?

回答

6

在EclipseLink的,你可以使用如果你使用@CascadeOnDelete注解。 EclipseLink还会为您生成级联DDL。

见, http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade

这通过让数据库优化删除做到这一点,也通过删除的对象保持高速缓存和持久性单元。

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

+0

看看我在找什么!太糟糕了,它是供应商的具体情况,但它必须这样做。谢谢! – 2011-04-26 14:18:00

3

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

  • 数据库可能是快了很多这样
  • 数据库应保持完整性和关系信息的主要场所。 JPA只是反映了信息
  • 如果您正在使用不同的应用/平台的连接(即没有JPA),你仍然可以cascadingly删除您的记录,这有助于提高数据的完整性
+0

我同意你的观点,但是你确定实体经理不应该被通知一些对象已被删除吗?也许最坏的情况是一些死对象被缓存(但通常不可访问,因为这将通过被移除的父对象)几分钟。如果我在数据库和JPA中都指定了级联,则可以忽略第二点和第三点。你对这个选择有什么看法? – 2011-04-26 09:18:28

+1

你说得对,对不起,我没有彻底读过你的问题。我想这取决于JPA的实施。很可能,您可以指定在数据库AND和JPA注释类中级联删除。一个好的实现应该通过刷新它的缓存来反映这一点。但是最后一次我使用JPA(很久以前和Hibernate一起),显然情况并非如此。解决方法是禁用所有缓存... – 2011-04-26 09:27:00

0

This answer引发了一些关于为什么它应该是JPA处理级联而不是数据库的真正强有力的论点。

下面是相关报价:

...如果你将使数据库级联,并在 休眠(性能问题)不声明它们,你可以在某些情况下获得 错误。这是因为Hibernate在其会话缓存中存储实体 ,所以它不知道数据库删除 cascade中的某些内容。

当您使用二级缓存,你的情况更糟,因为 这个缓存的生活比会话和DB-侧这样的变化不再会 是不可见的,只要旧值存储在此 缓存其他场次。