2017-05-03 126 views
1

我看到很多類似的問題,但還沒有找到將結合在一起的結論。級聯在JPA @OneToMany中刪除與數據庫級聯外鍵刪除

使用JPA時,如果您有@OneToMany關係,可以指定級聯REMOVE操作。同時,可以在數據庫中指定外鍵,並在鍵基行被刪除時採取動作。

JPA例如:

@Entity 
public class Parent { 

    @Id 
    private Long id; 
    @OneToMany(cascade = {CascadeType.REMOVE}) 
    private List<Child> children; 
    // getters, setters... 

} 

@Entity 
public class Child { 

    @Id 
    private Long id; 
    @ManyToOne(optional = false) 
    @JoinColumn(name = parent_id, nullable = false) 
    private Parent parent; 
    // getters, setters... 

} 

在數據庫中,Child表將不得不與一個外鍵約束的Parentid列列parent_id

在該級聯刪除的外鍵約束上可能執行的某些操作是delete,set to nulldo nothing。這給出了以下場景組合。

 
     JPA | cascade | no cascade | 
      | remove | remove  | 
DB FK  |   |   | 
-----------+---------+------------| 
delete  | A |  D  | 
-----------+---------+------------| 
set null | B |  E  | 
-----------+---------+------------| 
do nothing | C |  F  | 
-----------+---------+------------+ 
  • 答:級聯刪除呼叫父在JPA,對父行的刪除數據庫中刪除的孩子,他們有一個外鍵。
  • B:在JPA中級聯刪除,將父表中的外鍵列設置爲null,在父刪除的數據庫中爲空。在這種情況下,@JoinColumn中的nullable和/或@ManyToOne中的optional可能需要爲true/false。
  • C:Cascade在JPA中刪除,在數據庫中不做任何外鍵刪除。
  • D:不要在JPA中級聯刪除,在數據庫中級聯刪除父級。 E:不要在JPA中級聯刪除,將父表中的子表中的外鍵列設置爲在父刪除中的數據庫中爲空。 F:不要級聯刪除JPA中的數據庫,在外鍵刪除時什麼也不做。

所以,關於這個問題。

以下哪種情況會導致異常?如果圖C會。如果通過EntityManager刪除Parent實例,則該調用首先在該實例上完成,然後級聯到collection屬性中的Child實例。但是,在沒有首先刪除相關子項的情況下嘗試從數據庫中刪除父項會導致外鍵違規。它是否正確?是否有其他錯誤的情況? Woud試圖從已經從基礎數據庫中刪除的持久性中刪除實體時遇到問題?

這使EntityManager緩存處於與數據庫不一致的狀態嗎?我認爲它是D和E.在這些情況下,您必須自己爲子列表中的實例調用remove()

您應該使用哪種設置來強制實現JPA層和數據庫中的數據一致性?請問A會這樣做嗎?我認爲B也可以工作,因爲數據庫本身會在刪除父項時將外鍵列設置爲空(不再違反約束),然後JPA可以刪除子實例。

回答

0
  • 異常方案:

我覺得B,和E會導致過多的例外,因爲外鍵字段不爲空。

使用null更新其值時,會引發異常。

  • 實現JPA和數據庫的一致性

我認爲使用A,或F將實現它。在他們兩人中,兩個層次都會採取相同的行動。