2011-08-25 62 views
63

說我有類似下面的單向@ManyToOne關係:JPA:單向許多-to-one和級聯刪除

@Entity 
public class Parent implements Serializable { 

    @Id 
    @GeneratedValue 
    private long id; 
} 

@Entity 
public class Child implements Serializable { 

    @Id 
    @GeneratedValue 
    private long id; 

    @ManyToOne 
    @JoinColumn 
    private Parent parent; 
} 

如果我有一個家長P和兒童ç。C n引用回P,是否有一個乾淨漂亮的方式在JPA中自動刪除孩子C ... C n當刪除P(即entityManager.remove(P))?

我在找的是一個與SQL中的ON DELETE CASCADE類似的功能。

+1

即使只有'Child'對'Parent'的引用(以這種方式引用是單向的),添加帶有'@OneToMany'映射的'Child'列表和'Cascade = ALL '屬於'父'?我認爲JPA應該解決這個問題,即使只有一方擁有這個參考。 – kvDennis

+1

@kvDennis,有些情況下你不希望將多方緊密結合在一起。例如。在ACL類似的安全權限是透明的「附加」設置 – Bachi

回答

56

JPA中的關係始終是單向的,除非您在兩個方向上將父項與子項相關聯。將父級的REMOVE操作級聯到子級將需要父級與子級的關係(而不僅僅是相反)。

你會因此需要這樣做:

  • 要麼,單向@ManyToOne關係改變爲雙向@ManyToOne,或單向@OneToMany。然後,您可以級聯REMOVE操作,以便EntityManager.remove將刪除父級和子級。您還可以指定orphanRemoval爲true,以便在父集合中的子實體設置爲空時刪除任何孤兒,也就是說,如果該子實體不存在於任何父級集合中,則將其刪除。
  • 或者,在子表中指定外鍵約束爲ON DELETE CASCADE。在調用EntityManager.remove(parent)之後,需要調用EntityManager.clear(),因爲需要刷新持久性上下文 - 子對象在數據庫中被刪除後不應存在於持久性上下文中。
+4

是否有辦法用JPA註釋做No2? – user2573153

+2

如何用Hibernate xml映射做No2? – arg20

+0

回答下面你的方式比你的方式更好 – Enerccio

11

創建一個雙向的關係,就像這樣:

@Entity 
public class Parent implements Serializable { 

    @Id 
    @GeneratedValue 
    private long id; 

    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE) 
    private Set<Child> children; 
} 
+0

不好的答案,雙向關係在JPA很糟糕,因爲在大型兒童套裝上操作需要很多時間 – Enerccio

-1

@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

定的註釋爲我工作。

例如: -

 public class Parent{ 
      @Id 
      @GeneratedValue(strategy=GenerationType.AUTO) 
      @Column(name="cct_id") 
      private Integer cct_id; 
      @OneToMany(cascade=CascadeType.REMOVE, fetch=FetchType.EAGER,mappedBy="clinicalCareTeam", orphanRemoval=true) 
      @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
      private List<Child> childs; 
     } 
      public class Child{ 
      @ManyToOne(fetch=FetchType.EAGER) 
      @JoinColumn(name="cct_id") 
      private Parent parent; 
    } 
39

如果你正在使用Hibernate作爲JPA提供者,你可以使用註解@OnDelete。此註釋將添加到觸發器ON DELETE CASCADE的關係上,該關係將子項的刪除委託給數據庫。

例子:

public class Parent { 

     @Id 
     private long id; 

} 


public class Child { 

     @Id 
     private long id; 

     @ManyToOne 
     @OnDelete(action = OnDeleteAction.CASCADE) 
     private Parent parent; 
} 

通過這一解決方案,從孩子到家長的單向關係,就足以自動刪除所有的孩子。這個解決方案不需要任何監聽器等。另外一個查詢如DELETE FROM Parent WHERE id = 1將刪除這些子項。

+0

這是一個完美的解決方案,無需更改@ManyToOne設計。 –

+0

這是一個很好的答案,它甚至不是一個選項,它是一個重要的功能 – Yoi

+2

我不能讓它這樣工作,是否有任何特定版本的休眠或其他更詳細的例子是這樣的? – Mardari