2015-06-23 67 views
2

我有FamilyPerson之間的雙向映射:併發插入到實體集合

@Entity class Family { 
    @OneToMany(mappedBy = "family", ...) 
    Set<Person> persons; 
    ... 
} 

@Entity class Person { 
    @ManyToOne 
    Family family; 
    ... 
} 

我的問題是,我可以同時添加和/或刪除的集合,它打破原子在更新的元素,如增加一個新人創建INSERT INTO Person ...聲明不會與其他插入相沖突。 @Version字段沒有幫助,因爲我沒有更新Family實體作爲表中的行,只是邏輯上。

我應該怎麼做才能啓用集合的原子更新?我已經嘗試加載FamilyLockMode.PESSIMISTIC_WRITE,它可以同步Family本身的更新,但不允許第二級緩存讀取Family。我寧願在數據庫中使用謂詞約束進行樂觀事務。

+0

因此你必須使用交易! –

回答

2

您可以使用OPTIMISTIC_FORCE_INCREMENT

entityManager.lock(family, LockModeType.OPTIMISTIC_FORCE_INCREMENT); 

這樣的版本將被選中並在相應的Family實體實例遞增。

編輯

由於您使用的L2高速緩存,以及由於某種原因(BUG,設計決策,或者只是缺少功能)Hibernate不更新力增加後的版本在L2高速緩存,必須真正擁有此鎖加載實體一切正常工作:

entityManager.find(Family.class, id, LockModeType.OPTIMISTIC_FORCE_INCREMENT); 

不過,現在你必須照顧要一致,並通過這種方式加載Family實體更新它們總是之前(以避免使用陳舊的版本值,因爲e L2緩存與數據庫不同步)。

爲了解決這個問題,你可以在Family實體中添加一個虛擬列,比如lastUpdateTime或其他東西,並且更新Family實例而不使用任何明確的鎖定。然後常規版本檢查將會發生,並且所有內容都將與L2緩存同步。

+0

看來,這工作,雖然我現在從數據庫(H2 1.3.176)獲取一些鎖定超時...一旦我找出發生了什麼,我會將其標記爲正確。 –

+0

謝謝,我會看看爲什麼L2不通知緩存。目前我仍在嘗試修復L2 Infinispan實施,因爲在使用羣集緩存時存在一些一致性問題。 –