2016-02-23 22 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我們改變主意:)