2016-02-23 24 views
1

TL; DR:是否可以配置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. 允许级联删除发生在数据库级别。由于数据在幕后发生变化,我假设我需要记住手动收集子集合以防止Hibernate和数据库之间的差异。

编辑:我看到Hibernate老的版本中使用有one-shot delete的概念,但我无法找到最新版本的文档中类似的事情。该功能已被删除?

回答

2
  1. 说你删除一个父。
  2. 如果某个其他表(如GrandChild)具有带有Child的外键约束 ,并且每个孩子都有多个GrandChild记录,则他们也需要删除它们 。
  3. 多个生成的删除查询的原因是,Hibernate可能 不知道是否存在来自其他 表的任何外键约束到“子”表。也可能有一些需要执行的回调方法,例如@PreRemove。这就是每个Child引用从数据库加载并单独删除的原因。
  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; 
    
+1

谢谢,这是有道理的。如果我在数据库中添加级联删除会导致Hibernate的缓存问题? –

1

这似乎过于简单,所以也许我没有正确理解你的问题,而是:

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

如果我们能。清楚()我们的孩子,就像那样。也许更好地软删除他们incase我们改变主意:)