7

我正在编写一个小型 Grails 应用程序,并且在运行以下相当简单的代码时,我继续获得 StaleObjectStateException:s 大约 1/10:th 对“createfoo”的调用。很可能我错过了使用 GORM 的最佳方式。

这是代码:

def viewfoo = {
  session.user.refresh()
  // ...
}

def createfoo = {
  session.user.refresh()
  var user = session.user
  if (param["name"]) {
    var newFoo = new Foo()
    newFoo.name = param["name"]
    if (newFoo.validate()) {
      newFoo.save()
      if (user.validate()) {
        user.addToFoos(newFoo)
      } else {
        user.discard()
      }
    } else {
      newFoo.discard()
    }
  }
}

我关于 GORM 最佳实践的问题:

  1. “if-validate()-then-save()-else-discard()”是在 GORM 中持久化新对象的正确方法吗?

  2. 我应该验证我将要保存()的所有对象吗?即我应该在上面的代码中同时验证 Foo 对象和用户对象吗?验证用户对象会隐式检查 Foo 对象的状态吗?

  3. 我做了什么才能得到 StaleObjectStateException?:-)

GORM/休眠异常:

原因:具有标识符 [15] 的类 [Foo] 的对象:乐观锁定失败;嵌套异常是 org.hibernate.StaleObjectStateException:行已被另一个事务更新或删除(或未保存的值映射不正确):[Foo#15]
4

2 回答 2

2

我注意到的一件事是您没有保存用户,即使您刚刚添加了一些 foo 。事实上,保存用户应该避免需要保存 foo。

您不必验证用户:它的属性不会被不受信任的来源更改,并且无论何时保存都会检查数据库级别的约束。

最后,像 user.refresh() 这样的东西最好移到你的操作之外并进入拦截器或过滤器。

于 2009-01-28T20:06:05.943 回答
2

我不确定您为什么会遇到问题,但是域对象上有一种合并方法。它允许您将当前对象重新附加到当前持久上下文。

我不太了解您的 Foo,或者您对 User 对象进行了哪些自定义,或者您使用的 grails/java 版本以便能够重现这一点。

我认为这与您在用户对象上进行的刷新有关,这导致数据库版本得到更新(因此不同步),但我不能确定。

此外,根据这篇文章的评论,我相信在 grails 1.1 中验证然后丢弃的行为正在发生变化并且不太必要

于 2009-01-28T21:26:01.320 回答