2011-04-26 97 views
10

比方說,我們有兩個實體,A和B. B有很多一對一關係提升到一個類似如下:我應該讓JPA還是數據庫級聯刪除?

@Entity 
public class A { 
    @OneToMany(mappedBy="a_id") 
    private List<B> children; 
} 

@Entity 
public class B { 
    private String data; 
} 

現在,我要刪除的目的和級聯刪除其所有孩子(B)。有兩種方法可以做到這一點:

1)將cascade=CascadeType.ALL, orphanRemoval=true添加到OneToMany批註中,讓JPA在從數據庫中刪除A對象之前刪除所有的孩子。

2)讓類保持原樣,只是讓數據庫級聯刪除。

使用後面的選項有什麼問題嗎?它會導致實體管理器保持對已經刪除的對象的引用嗎?我選擇選項二的原因在於,選項一生成n + 1個SQL查詢以進行刪除操作,當對象A包含大量子項時可能需要很長時間,而選項二隻生成一個SQL查詢,然後繼續愉快。有沒有關於這方面的「最佳做法」?

回答

6

在EclipseLink的,你可以使用如果你使用@CascadeOnDelete註解。 EclipseLink還會爲您生成級聯DDL。

見, http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade

這通過讓數據庫優化刪除做到這一點,也通過刪除的對象保持高速緩存和持久性單元。

請注意,orphanRemoval = true也會刪除從集合中刪除的對象,而數據庫級聯約束不會爲您執行這些操作,因此擁有JPA中的規則仍然是必需的。還有一些數據庫無法處理刪除的關係,因爲數據庫只能以約束的反方向級聯,具有外鍵的OneToOne或具有連接表的OneToMany無法級聯到數據庫。

+0

看看我在找什麼!太糟糕了,它是供應商的具體情況,但它必須這樣做。謝謝! – 2011-04-26 14:18:00

3

我更喜歡數據庫。爲什麼?

  • 數據庫可能是快了很多這樣
  • 數據庫應保持完整性和關係信息的主要場所。 JPA只是反映了信息
  • 如果您正在使用不同的應用/平臺的連接(即沒有JPA),你仍然可以cascadingly刪除您的記錄,這有助於提高數據的完整性
+0

我同意你的觀點,但是你確定實體經理不應該被通知一些對象已被刪除嗎?也許最壞的情況是一些死對象被緩存(但通常不可訪問,因爲這將通過被移除的父對象)幾分鐘。如果我在數據庫和JPA中都指定了級聯,則可以忽略第二點和第三點。你對這個選擇有什麼看法? – 2011-04-26 09:18:28

+1

你說得對,對不起,我沒有徹底讀過你的問題。我想這取決於JPA的實施。很可能,您可以指定在數據庫AND和JPA註釋類中級聯刪除。一個好的實現應該通過刷新它的緩存來反映這一點。但是最後一次我使用JPA(很久以前和Hibernate一起),顯然情況並非如此。解決方法是禁用所有緩存... – 2011-04-26 09:27:00

0

This answer引發了一些關於爲什麼它應該是JPA處理級聯而不是數據庫的真正強有力的論點。

下面是相關報價:

...如果你將使數據庫級聯,並在 休眠(性能問題)不聲明它們,你可以在某些情況下獲得 錯誤。這是因爲Hibernate在其會話緩存中存儲實體 ,所以它不知道數據庫刪除 cascade中的某些內容。

當您使用二級緩存,你的情況更糟,因爲 這個緩存的生活比會話和DB-側這樣的變化不再會 是不可見的,只要舊值存儲在此 緩存其他場次。