2017-02-21 119 views
0

我有兩個實體:TalkUser。用戶可以創建很多會談,併成爲這些會談的「組織者」。當組織者被刪除時,它的談話也應該被刪除。當一個談話(由某個組織者創建)被刪除時,不應該刪除任何用戶,但談話當然應該從數據庫中刪除,但這是而不是發生在我的情況!刪除不在雙向ManyToOne關係

所以,這裏是我到目前爲止所代表什麼,我一直在說的代碼:

// Talk.java 

@Entity 
public class Talk implements Serializable { 

    ... 

    @ManyToOne(cascade = {CascadeType.REFRESH, CascadeType.PERSIST}) 
    @JoinColumn(nullable = false, name = "TALK_ORGANIZER_FK") 
    protected User organizer; 

    ... 

// User.java 

@Entity 
public class User implements Serializable { 

    ... 

    @OneToMany(mappedBy = "organizer", cascade = {CascadeType.REFRESH, CascadeType.REMOVE}) 
    protected List<Talk> organizedTalks; 

    ... 

大多數的方法來處理這兩個實體之間的關係將從Task實體調用。例如,當我需要將用戶添加到講話中時,我會撥打addParticipant,然後調用joinTalk,在User中定義。

所以,我看到這個問題可能是由於cascade屬性的使用不一致造成的。所以這就是爲什麼我要解釋爲什麼我使用了我用過的東西。

我增加了CascadeType.REFRESHCascadeType.PERSIST選項來organizer字段中Talk實體,因爲,每當我把談話的組織者,如果不存在的話,我想將它存儲在數據庫中,而且由於,如果存在,我想更新它(最終)。

我添加的選項CascadeType.REFRESHCascadeType.REMOVE到外地organizedTalks在實體User,因爲:

  1. 每當我刪除一個用戶,我想在級聯
  2. ,每當被刪除與其相關的會談中,我更新用戶,我想它的相關談判也被更新

  1. 目前,當我刪除用戶,其所有相關的談判被刪除(如預期!​​)

  2. 要麼,如果我嘗試刪除使用deleteAllremoveByField談話,它不會刪除任何談話,即使它返回,在第二種情況下,假設被刪除的實體的數量(這是上面描述的實際問題!)。

因爲我並不是真的是使用JPA的專家,所以我認爲你可以幫助我解決我的具體問題。

編輯

這是我觀察到的問題的特定測試:

@Test 
public void testRemoveByTitleTalkWhenJustOneParticipant() { 
    Talk t = new Talk("auditorium", new Date(), organizer); 
    entityManager.persist(t); 

    assertEquals(talkRepository.removeByTitle("auditorium"), new Long(1)); 

    assertEquals(talkRepository.count(), 0); // ERROR: EXPECTED 1 
    assertEquals(userRepository.count(), 1); // ONLY halloween WAS STORED 
    assertEquals(organizer, userRepository.findOneByName("halloween")); 
} 
+0

你可以顯示你嘗試和刪除你的談話方法的代碼嗎? 如果您的用戶對象處於hibernate上下文中,並且它的列表中仍然存在該對話,則可能是它不會被刪除的原因。 – TheBakker

+0

@TheBakker請看我的答案,它解決了這個問題,但我並不真正理解爲什麼(儘管如我所說,它與你剛纔所說的有些相關)。也許你可以猜得更好。 – nbro

回答

0

我剛剛發現了這個問題,它在某種程度上關係到什麼TheBakker剛剛在評論說:低於問題。

User實體我有另一個領域:

@ManyToMany(mappedBy = "participants", cascade = {CascadeType.REFRESH, CascadeType.PERSIST}) 
protected List<Talk> assistedTalks; 

和那些級聯選項,如果去掉,如果該字段被簡單地聲明,即作爲

@ManyToMany(mappedBy = "participants") 
protected List<Talk> assistedTalks; 

解決我的問題。就我而言,顯然,我不需要這些選項(但另一個有類似問題的人可能需要它們,所以小心!)。

只是爲了背景化一點點。如果用戶組織講話,則最後一個會自動添加到assistedTalksorganizedTalks的列表中。

如果有人想以詳細解釋爲什麼發生這種情況,我會很感激。

+0

你可以顯示你的'Talk'構造函數嗎? – TheBakker

+0

@TheBakker'Talk'構造函數沒有什麼特別之處:初始化數組列表,設置標題,日期和演講的組織者(它也被添加爲演講的參與者,即它被添加到跟蹤的參與者列表中)通過'Talk')。設置管理器時,我還從'User'實體調用方法'organizTalk',它將講話添加到'用戶'的'assistedTalks'和'organizedTalks'列表中。 – nbro

+0

這可能是問題,你可以發佈它嗎? – TheBakker

1

當你調用entityManager.persist(t);,要保存的談話到數據庫中,而且組織者和輔助型和舉辦講座,談2間之間的聯繫。 如果你的組織者還沒有堅持,他現在是。

然後嘗試並刪除與talkRepository.removeByTitle("auditorium")

談話不過既然講的是仍然在這兩個用戶集合協助和組織。 而輔助收集有CascadeType.PERSIST它會保持它持續。

如果您想保留註釋原樣,您需要在java中刪除輔助集合中的對話,然後我認爲它會起作用。