2010-09-10 43 views
2

我的問題是類似JPA最佳實踐問題 - 更新一個字段只

Updating one field in JPA entity

基本上我有其中有一些基本的字段(enumStringDateTime),它有兩個其他領域的實體美孚。其中之一是OneToOne,另一個是使用集合實現的OneToMany。

我有兩個線程它們在不同的時間運行,並查找使用findById類型的方法在辛格爾頓的EntityManager包裝類相同的實體(我沒有寫這一點;)

我想什麼,以避免是以下情況:

線程1查找一個Foo其中具有1的ID和它得到在該時間點的基準,以與富富的狀態。

線程2查找一個Foo其中具有1的ID,並得到一個裁判的Foo與相同的狀態的線程1

線程1改變上富字符串字段中,並用合併 線程持續,2更改foo上的Enum字段的值並將其保留爲合併結果

上次操作導致更改線程1被替換爲線程2得到的舊字段的狀態,因爲合併正在更新所有內容(除外OneToOne和OneToMany,因爲它們的CascadeType是Persist和Remove)。

我所尋找的是建議,以最佳實踐方法將防止這種狀態重挫當一個人只需要更新以這種方式具體領域的東西。

雖然我有,我認爲是在我的帖子頂部的鏈接中提到的,但它改變了使用現在使用的通用save(Object o)的東西,它將合併到特定於這種情況下,從實體ID鍵入的特定字段上執行UPDATE。有沒有更好的辦法?我目前的持久性提供者是EclipseLink。

TIA

-NBW

+0

你能發表一些代碼嗎? – 2010-09-11 02:45:55

+0

請參閱[這裏]的答案(http://stackoverflow.com/questions/3476613/updating-one-field-in-jpa-entity/18875850#18875850)查看JPA 2.1支持部分實體更新 – 2013-09-18 15:06:42

回答

0

首先,你可以利用該處理這類情況的交易。如果性能不是問題,請使用悲觀鎖定並解決問題 - 第二個線程將等待第一個線程更新值。

但我同意這個用例應該有更簡單的東西。您可以使用普通JDBC並撰寫更新查詢。

3

你應該用樂觀鎖(@版本)在JPA。這會導致第二個客戶端的事務失敗。

另外的EclipseLink只會更新變化的領域,所以如果你讀這兩個對象進入交易/持久化上下文,他們只會更新他們改變了場。讓它恢復更改的唯一方法是,如果在讀取對象後對其進行序列化或分離,然後將其合併回新的持久性上下文中。 (請注意,merge()僅適用於分離的對象,因爲它們已經被管理,所以不應該用於管理對象)。

1

Thread1引用Foo的分離實例,並且thread2引用Foo的diff實例,樂觀鎖定(@Version)將不起作用,因爲當您嘗試第二次保存分離的實例時,它將引發異常,Best方法來解決你的問題是你合併之前要做到這一點,每次你脫離實體

SOL1: //加載富每次你改變 富= em.find(foodId,讓Foo.class); //foo.set ..使變化 em.merge(富)

SOL2: // FOO指的是分離的實體 em.refresh(FOO); //foo.set .. make change em.merge(foo)