假设我有一个使用原始SQL更新计数器的计数器函数:
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方式"是什么?
你可以使用'悲观'或'乐观'锁定策略,这些策略既得到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 } ...
如果您更喜欢'悲观'锁定策略(它将阻止所有其他并发读取,顺便说一句),您可以使用显式'lock'GORM元方法来执行此操作,如下所示:
... 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 ...
希望这可以帮助.