在Grails中使用GORM时的并发性
-
03-07-2019 - |
题
假设我有一个使用原始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-way”?处理这个并发问题?
解决方案
你可以使用'悲观'或'乐观'锁定策略,这些策略既得到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
...
希望这有帮助。
不隶属于 StackOverflow