hibernate - 如何克服Grails Service中的StaleObjectStateException

标签 hibernate grails transactions service optimistic-locking

我介绍了一个TransactionService,我在 Controller 中使用它来执行乐观交易。这应该

  • 尝试执行给定的事务(=关闭)
  • 如果失败则回滚,然后
  • 如果失败,请重试

  • 基本上看起来像这样:
    class TransactionService {
      transactional = false // Because withTransaction is used below anyway
      def executeOptimisticTransaction(Closure transaction) {
        def success = false
        while (!success) {
          anyDomainClass.withTransaction { status ->
            try {
              transaction()
              success = true
            } catch(Exception e) {
              status.setRollbackOnly()
            }
          }
        }
      }
    }
    

    它稍微复杂一点,例如它在再次尝试之前使用不同的Thread.sleeps,并在某个阶段中止,但这并不重要。它由传递事务的 Controller 调用,以作为闭包安全地执行。

    我的问题:当服务由于并发更新而遇到org.hibernate.StaleObjectStateException时,它将继续尝试,但该异常永不消失。

    我已经尝试过其他方法,例如在 Controller 传递的事务中重新附加域类,清除服务或 Controller 中的 session ,但这无济于事。我想念什么?

    我应该注意,当我尝试使用status.createSavepoint()调用transaction()之前插入一个savePoint时,出现了一个错误,即“Transaction Manager不允许嵌套事务”。我尝试此操作是因为我还怀疑该错误存在,因为该事务已从 Controller 传递到服务,并且我需要启动一个新的/嵌套事务来避免它,但是由于错误显示在我的情况下这是不可能的。

    还是将交易作为关闭传递是问题所在?

    我假设.withTransaction之前使用的域类无关紧要,还是那样?

    最佳答案

    它不是闭包本身,但我相信transaction里面有一些过时的变量引用。
    如果您尝试只传递在执行时重新读取其对象的闭包怎么办?喜欢

    executeOptimisticTransaction {
      Something some = Something.get(id)
      some.properties = aMap
      some.save()
    }
    

    我认为在不重新休眠的情况下“刷新”对象是不可能的。

    是的,在什么类上调用.withTransaction()都没有关系。

    对于更新计算的总数/额定值的示例,这是一个数据重复,这本身就是一个问题。我宁愿:
  • 创建一个(Quartz)作业,该作业将基于一些“脏”标志来更新等级-这可以节省一些DB CPU,但要花费更新时间;
  • 或在SQL或HQL中进行操作,例如将使用最新Rating的Book.executeQuery('update Rating set rating=xxx')。如果您正在针对重载进行优化,那么无论如何您将不会做任何Groovy方式。不要将Rating对象保存在Grails中,只能阅读它们。
  • 关于hibernate - 如何克服Grails Service中的StaleObjectStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4375757/

    相关文章:

    java - JPA 中的 CriteriaBuilder - where 子句

    java - 从数据库中选择 MappedSuperclass (Hibernate)

    在 Grails 中缓存域对象

    MySql InnoDB可重复读取锁的意外行为

    java - 如何跨 Web 应用程序共享 Hibernate SessionFactory?

    java - 恩弗斯 : wrong audit table on a Spring MVC project

    rest - 使用 HTTPBuilder 进行 HTTPS 的 Grails REST 插件

    java - grails 不会保存但没有错误

    java - 在 Java 中完成事务的正确代码模式是什么(异常回滚并成功提交)?

    数据库事务——它们是如何工作的?