【问题标题】:Concurrency when using GORM in Grails在 Grails 中使用 GORM 时的并发性
【发布时间】:2009-03-05 22:27:56
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: hibernate grails concurrency transactions grails-orm


    【解决方案1】:

    您可以使用“悲观”或“乐观”锁定策略,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
    }
    ...
    

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

    希望这会有所帮助。

    【讨论】:

    • 你说的“在这里处理并发修改”是什么意思?你的意思是使用“合并”或其他什么?干杯
    猜你喜欢
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多