grails - grails 何时检查对象过时性?

标签 grails grails-orm staleobjectstate

我正在使用 Grails 2.5.1,并且我有一个 Controller 调用一个服务方法,它偶尔会导致 StaleObjectStateException .服务方法中的代码在 obj.save() 周围有一个 try catch。只是忽略异常的调用。但是,每当发生这些冲突之一时,日志中仍然会打印一个错误,并向客户端返回一个错误。

我的游戏 Controller 代码:

def finish(String gameId) {
   def model = [:]
   Game game = gameService.findById(gameId)

   // some other work

   // this line is where the exception points to - NOT a line in GameService:
   model.game = GameSummaryView.fromGame(gameService.scoreGame(game))

   withFormat {
     json {
        render(model as JSON)
     }
   }
}

我的游戏服务代码:
Game scoreGame(Game game) {
   game.rounds.each { Round round ->
      // some other work
         try {
             scoreRound(round)
             if (round.save()) {
                 updated = true
             }
         } catch (StaleObjectStateException ignore) {
             // ignore and retry
         }
   }
}

堆栈跟踪显示异常从我的 GameController.finish 生成。方法,它不指向我的 GameService.scoreGame 中的任何代码方法。这对我来说意味着 Grails 在事务启动时检查陈旧性,而不是在尝试保存/更新对象时?

我多次遇到这个异常,通常我通过不遍历对象图来修复它。

例如,在这种情况下,我会删除 game.rounds引用并将其替换为:
def rounds = Round.findAllByGameId(game.id)
rounds.each {
   // ....
}

但这意味着在创建事务时不会检查陈旧性,并且它并不总是实用的,并且在我看来有点违背 Grails 惰性集合的目的。如果我想自己管理所有的协会,我会的。

我已阅读有关 Pessimistic and Optimistic Locking 的文档,但我的代码遵循那里的示例。

我想了解更多关于 Grails (GORM) 如何/何时检查陈旧性以及在哪里处理它的信息?

最佳答案

您没有显示或讨论任何事务配置,但这可能是造成困惑的原因。根据你所看到的,我猜你有 @Transactional Controller 中的注释。我这么说是因为如果是这种情况,事务就会从那里开始,并且(假设您的服务是事务性的)服务方法会加入当前事务。

在您调用的服务中save()但你不刷新 session 。这对性能更好,特别是如果您在工作流的另一部分进行其他更改 - 当您可以一次推送所有更改时,您不希望向每个对象推送两组或更多组更新。由于您不刷新,并且由于事务不会像 Controller 未启动事务那样在方法结束时提交,因此仅在 Controller 方法完成并且事务提交时才会推送更新。

您最好将所有事务(和业务)逻辑移至服务并从 Controller 中删除所有事务跟踪。除非您愿意承受性能损失,否则避免通过急切地冲洗来“解决”这个问题。

至于过时检查 - 它相当简单。当 Hibernate 生成 SQL 以进行更改时,它的格式为 UPDATE tablename SET col1=?, col2=?, ..., colN=? where id=? and version=? . id 显然会匹配,但是如果版本增加了,那么 where 子句的版本部分将不匹配,并且 JDBC 更新计数将为 0,而不是 1,这被解释为意味着其他人在您阅读和更新数据。

关于grails - grails 何时检查对象过时性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32685543/

相关文章:

grails - Groovy-更改嵌套 map 中字符串的值

Grails GORM Criteria Query Eager Fetching

Grails 按日期分组

hibernate - grails中的withTransaction和withSession有什么区别?

grails - 从Grails的数据库设置配置值

grails - Grails 3.3如何减少控制台输出?

hibernate - 如何使用 JPA 和 Hibernate 修复 StaleObjectStateException

java - Hibernate - 查询中的 StaleObjectStateException 可能吗?

grails 4 - 使用代码进行本地化绑定(bind)时,BindingFormat 注释不绑定(bind)日期