【问题标题】:Hibernate: Delete all children with one queryHibernate:用一个查询删除所有子节点
【发布时间】:2021-04-30 08:53:39
【问题描述】:

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;
}

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

可能的解决方法

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

编辑:我看到旧版本的 Hibernate 曾经有 one-shot delete 的概念,但我在最新版本的文档中找不到类似的东西。该功能是否已被删除?

【问题讨论】:

    标签: java hibernate orm parent-child cascade


    【解决方案1】:

    这可能看起来过于简单,所以也许我没有正确理解您的问题,但是:

    Parent parent = parentRepository.findByName("dad");
    parent.getChildren().clear();
    entityManager.save(parent);
    

    如果我们可以 .clear() 我们的孩子,就像那样。也许最好软删除它们以防我们改变主意:)

    【讨论】:

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

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

      【讨论】:

      • 谢谢,这是有道理的。如果我在数据库中添加级联删除,会导致 Hibernate 的缓存出现问题吗?
      • 如果我没有 orphanRemoval=true,这是有道理的,但如果我这样做 - 这意味着我希望在父母离开时删除孩子,这意味着我确信有没有孙子,或者我应该在删除之前照顾他们。不过,您关于@PreRemove 的观点仍然有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2015-10-06
      相关资源
      最近更新 更多