2009-03-05 38 views
2

比方說,我有使用原始SQL,其更新計數器的計數功能:併發Grails中使用GORM時

public void updateCounter() { 
    executeSql("UPDATE counter SET count_value = count_value + 1 WHERE id = 1;"); 
} 

該數據庫將確保按預期櫃檯兩個併發處理呼叫 - 所有調用會以一個增量更新計數器,並且不會有更新丟失。

而不是通過發出原始SQL命令來執行此操作我想使用GORM。用簡單的方式做這將是沿着線的東西:

public void updateCounter() { 
    Counter c = Counter.get(1) 
    c.countValue += 1 
    c.save() 
} 

在這種情況下,我認爲,如果兩個線程調用同一時刻updateCounter()方法的更新可能會丟失。什麼是正確的「Grails/GORM-way」來處理這個併發問題?

回答

6

您可以使用'悲觀'或'樂觀'鎖定策略,這兩種策略都由Hibernate支持,因此由GORM支持。默認的GORM策略是「樂觀的」(利用默認情況下創建的永久域實體的版本列/屬性)。它可以這樣來使用:

... 
try { 
Counter c = Counter.get(1) 
c.countValue += 1 
c.save(flush:true) 
} 
catch(org.springframework.dao.OptimisticLockingFailureException e) { 
// deal with concurrent modification here 
} 
... 

如果你喜歡「悲觀」的鎖定策略,而不是(這將阻止所有其他併發讀取,順便說一句),你可以使用顯式「鎖定」格姆元方法做到這一點,像這樣:

... 
Counter c = Counter.lock(1) //lock the entire row for update 
c.countValue += 1 
c.save(flush:true) //GORM will autorelease the lock once the TX is committed 
... 

希望這有助於。

+0

當你說「在這裏處理併發修改」時,你是什麼意思? 你的意思是使用「合併」還是其他? 乾杯 – Mulone 2010-05-25 14:55:03