在Grails中使用GORM时的并发性

时间:2021-12-19 06:51:41

Let's say I have a counter function which updates a counter using raw SQL:

假设我有一个使用原始SQL更新计数器的计数器函数:

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

The database would make sure that two concurrent calls to the counter are handled as expected - that all calls would update the counter with one increment and no updates would get lost.

数据库将确保对计数器的两个并发调用按预期处理 - 所有调用将以一个增量更新计数器,并且不会丢失任何更新。

Rather than executing this by issuing a raw SQL command I'd like to use GORM. The naïve way to do it would be something along the lines of:

而不是通过发出原始SQL命令执行此操作,我想使用GORM。这种天真的方式将是:

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

In this case I'd assume that an update could be lost if two threads call the updateCounter() method at the same moment. What is the correct "Grails/GORM-way" to handle this concurrency issue?

在这种情况下,我假设如果两个线程同时调用updateCounter()方法,则更新可能会丢失。处理这种并发问题的正确“Grails / GORM方式”是什么?

1 个解决方案

#1


You could use either 'pessimistic' or 'optimistic' locking strategies, which both supported by Hibernate and therefore by GORM. The default GORM strategy is 'optimistic' (which utilizes the version column/property of the persistent domain entity, created by default). It could be used like this:

你可以使用'悲观'或'乐观'锁定策略,这些策略既得到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
}
...

If you prefer the 'pessimistic' locking strategy instead (which will block all other concurrent reads, btw), you could do it using explicit 'lock' GORM meta-method, like so:

如果您更喜欢'悲观'锁定策略(它将阻止所有其他并发读取,顺便说一句),您可以使用显式'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
...

Hope this helps.

希望这可以帮助。

#1


You could use either 'pessimistic' or 'optimistic' locking strategies, which both supported by Hibernate and therefore by GORM. The default GORM strategy is 'optimistic' (which utilizes the version column/property of the persistent domain entity, created by default). It could be used like this:

你可以使用'悲观'或'乐观'锁定策略,这些策略既得到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
}
...

If you prefer the 'pessimistic' locking strategy instead (which will block all other concurrent reads, btw), you could do it using explicit 'lock' GORM meta-method, like so:

如果您更喜欢'悲观'锁定策略(它将阻止所有其他并发读取,顺便说一句),您可以使用显式'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
...

Hope this helps.

希望这可以帮助。