2011-04-27 31 views
0

我有以下幾點:休眠:在實體更新欄只有當特定字段爲空

public class Member { 

    @Id 
    @Column 
    private String id; 

    @Column 
    private String location; 

    // setters/getters 
} 

我要實現以下業務規則:

設置位置:

  1. 獲取來自基於ID的數據庫成員。
  2. 如果位置爲空,則將值分配給位置並保存,否則不執行任何操作。

public void setLocation(String id, String location){ 
    Member m = memberDao.find(id); // assume m is not null 
    if(null == m.getLocation()){ 
     m.setLocation(location); 
     memeberDao.saveOrUpdate(m); 
    } 
    else 
     throw new MemberAlreadyHasALocationException(); 
} 

刪除地點:

  1. 獲得基於ID從數據庫成員。
  2. 如果位置有一個非空值,電流值等於參數值,設置位置爲空和更新,否則什麼都不做

public void removeLocation(String id, String location){ 
    Member m = memberDao.find(id); 
    if(m.getLocation() != null && m.getLocation.equalsIgnoreCase(location)){ 
     m.setLocation(null); 
     memeberDao.saveOrUpdate(m); 
    } 
} 

我任務是處理併發性問題,但我不知道怎麼樣在休眠中做到這一點。更具體地說,我如何處理對同一ID的setLocation併發調用,因爲具有該ID的實體當前沒有位置。

基本上,第一次更新應該贏,第二次應該會失敗。

是否足以版本添加到成員類


@Version 
@Column(name="version") 
private Long version; 

不過,說是有一個性別字段,我希望能夠在不關心更新性別字段,如果該位置被由另一個事務更新。

謝謝。

回答

0

基本上,第一次更新應該贏得 ,第二次應該失敗。

是否足以版本添加到 會員類

是的,它的作用。假設你和我從版本= x的數據庫中讀取了一個實體。我對實體的property1進行了一些更改並提交給數據庫。現在數據庫中的實體具有版本= x + 1。現在,您更改了您的實體版本的property2(property1仍然保留較舊的值)。當您將更改的實體更新到數據庫時,由我對property1所做的更改將丟失,因爲您將使用舊值覆蓋它。但是這不會發生,因爲Hibernate會檢查讀取實體和更新它之間可能發生的任何更改。當你去更新實體時,Hibernate會發現數據庫中的實體版本與你提供的實體版本不同。這意味着別人已經對該對象進行了一些更改,即您提供的對象已過時,因此拋出了StaleStateException。

不過,說是有性別 場,我希望能夠 更新性別字段沒有如果該位置是由 其它事務更新的關懷 。

這是不可能使用休眠(從上面的例子應該清楚)。如果支持這一點,那麼當對性別進行更新時,對該位置所做的更改將會丟失,並且包含較舊的位置值。在更新實體之前,使用一些邏輯和顯式版本檢查和更新已更改的字段可以達到某種程度的容忍度,但問題仍然存在,您永遠無法知道將在什麼時候對對象進行更改。在我看來,這樣的實施將是一個沒有足夠好處的矯枉過正。

+0

感謝您的信息。我想現在,從休眠狀態轉移,我只想給位置一個值,只有當它爲空時才允許併發。但是,我不想阻止每次調用setLocation,而是要阻止對特定成員id的setLocation調用,以便兩個不同成員的setLocation調用不會被阻止,而是兩次調用setLocation爲同一個成員做塊。我還沒有找到一個好方法來做到這一點,我喜歡:http://stackoverflow.com/questions/659915/synchronizing-on-an-integer-value – jsl 2011-04-28 14:18:06

+0

只需使用一個存儲過程來檢查成員,如果他不存在,則返回-1,否則如果該成員確實存在並且他有一個位置,則返回0(不更新),否則更新該位置並返回1.數據庫是否會正確處理併發調用程序? – jsl 2011-04-28 14:22:16

+0

@jsl你應該檢查一下Hibernate中的悲觀鎖定。這將允許一次只允許一個線程對實體進行更改,阻止其他人想要對同一個實體進行更改。但是,這也會阻止想要更新位置以外的其他屬性的線程 – 2011-04-28 16:21:23