Hibernate:通过一个查询删除所有孩子

Ada*_*rod 5 java orm hibernate cascade parent-child

TL;DR:是否可以将 Hibernate 配置为使用单个删除查询删除所有子对象?


完整问题:我在 Hibernate 5.1 中定义了以下父/子关联:

public class Parent {
  @OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", cascade = CascadeType.REMOVE)
  private List<Child> children;
}

public class Child {
  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "parent_id", nullable = false)
  private Parent parent;
}
Run Code Online (Sandbox Code Playgroud)

当我删除父对象时,所有子对象都按预期删除,但每个子对象都被单独删除。在我的应用程序中,父级可能有数千个子级,因此出于性能原因,我需要使用单个查询一次将它们全部删除。

可能的解决方法

  1. DELETE FROM child WHERE parent_id = ?在删除父级之前手动执行我自己的 HQL 查询。这里的缺点是我(和任何其他开发人员)必须记住调用该方法。另外,它基本上绕过了级联删除。
  2. 允许级联删除发生在数据库级别。由于数据在幕后发生变化,我假设我需要记住手动.clear()设置子集合以防止 Hibernate 和数据库之间的差异。

编辑:我看到旧版本的 Hibernate 曾经具有一次性删除的概念,但我在最新版本的文档中找不到任何类似的内容。那个功能被删除了?

Ara*_*han 7

  1. 假设您删除了一个父级。
  2. 如果其他一些表,比如 GrandChild,有一个带有 Child 的外键约束,每个 Child 有多个 GrandChild 记录,它们也需要被删除。
  3. 生成多个删除查询的原因是,Hibernate 无法知道是否有任何来自其他表的外键约束,到“子”表。也可能有一些回调方法需要执行,例如@PreRemove。这就是为什么从数据库中加载每个子引用并单独删除的原因。
  4. 简而言之,如果您依赖 Hibernate 来管理您的实体,这是默认行为。
  5. 要么在数据库中显式设置 ON DELETE CASCADE,要么使用注释@org.hibernate.annotations.OnDelete 标记所需的 Child 实体,这会在模式生成期间自动将“删除时”添加到模式中。对于您的示例,它将是,

    `@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", 
                cascade = CascadeType.REMOVE)    
     @org.hibernate.annotations.OnDelete(
                action = @org.hibernate.annotations.OnDeleteAction.CASCADE)
     private List<Child> children;
    
    Run Code Online (Sandbox Code Playgroud)