使用元素集合时,如何在JPA中进行批量删除?

16
我在使用JPA进行批量删除Person对象时遇到了问题,其中Person对象包含使用@ElementCollection存储的数据。有没有什么好的方法可以实现这个功能呢?谢谢。

@Entity
@Table(name="at_person")
public class Person implements Comparable<Person> {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id")
    private long id = 0;

    @Column(name="name", nullable = true, length = 128)
    private String name = "";

    @ElementCollection
    @Column(name = "email")
    @CollectionTable(name = "person_email", joinColumns = @JoinColumn(name = "person_id"))
    private Set<String> email = new HashSet<String>();
}

我目前所做的是这样的,但它会出现外键约束错误:

Query query=em.createQuery("DELETE FROM Person");

由于外键约束,导致java.sql.SQLException: integrity constraint violation: foreign key no action; FKCEC6E942485388AB table: PERSON_EMAIL

如果可以使用纯JPA注解而不是Hibernate注解,那将是一个额外的奖励!

1个回答

29
我让你解释一下JPA 2.0规范中提到的批量删除操作不会级联的部分:

4.10 批量更新和删除操作

...

删除操作仅适用于指定类及其子类的实体。它不会级联到相关实体。

事实上,Hibernate也不会将删除级联到集合表中。这在HHH-5529中有记录,并且建议的方法是:

你可以(a)自己清理集合表或者(b)在模式中使用级联外键。

换句话说,(a)使用本机SQL或(b)在数据库层面使用级联删除约束 - 你需要手动添加,我认为你不能在@ElementCollection注释中使用@OnDelete(这就像HHH-4301的情况一样)。

11
哦,我很震惊JPA会有这样一个明显的漏洞。这意味着如果你想使用JPA清除非常大的表中的数据,你必须逐个迭代每个对象,或者希望手动开启级联删除!也许我应该重新审视一下JDO。 - corydoras
@corydoras我提到了选项。你做决定。 - Pascal Thivent
1
谢谢提供信息!人生苦短,不值得浪费时间在为本应简单的事情折腾解决方法上 (: 目前我们只能通过代码迭代每个对象并手动删除它们。 - corydoras
链接似乎对于5529无效,但应该在https://hibernate.atlassian.net/browse/HHH-5529上可用。 - arcuri82
无论如何,这可能是规格的一部分,但它看起来像是一个巨大的限制:(如果在JPA的下一个规格中不修复,如果在Hibernate中获得一些非标准的非JPA命令,那将是很好的...但是HHH-5529似乎自2010年以来就一直存在...我猜可能的解决方法是完全摆脱ElementCollection,并将基本元素包装在它们自己的实体中(尽管我猜这可能不是特别有效...) - arcuri82
Spec 2.1中的CriteriaDelete没有提到级联。JPA 2.1支持批量删除的级联吗? - eastwater

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接