GORM在Grails中的应用和StaleObjectStateException问题

7
我正在编写一个小的Grails应用程序,但是当运行以下简单代码时,“createfoo”的约1/10调用会出现StaleObjectStateException。很可能我错过了使用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-对象和User-对象?验证User对象是否会隐式检查Foo对象的状态?

  3. 我做了什么才配得上StaleObjectStateException?:-)

GORM / Hibernate异常:

Caused by: Object of class [Foo] with identifier [15]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Foo#15]
2个回答

2
我注意到的一件事是,尽管您刚刚添加了一些foo,但您并没有保存用户。实际上,保存用户应该可以避免保存foo的需要。
您不必验证用户:它的属性未被不受信任的来源更改,并且在保存时会检查数据库级别的约束条件。
最后,像user.refresh()这样的东西最好移出您的操作,并放入拦截器或过滤器中。

2
我不太确定你碰到了什么问题,但是在领域对象上有一个 merge 方法。 它可以让你重新连接当前对象到当前持久化上下文中。
我不知道你的 Foo,或者你对 User 对象做了哪些自定义,或者你正在使用的 grails/java 版本,以便能够重现这个问题。
我想这可能与你在用户对象上进行的刷新有关,这会导致数据库版本被更新(从而失步),但我不能确定。
另外,根据this post中的评论,我认为验证然后丢弃行为正在改变,并且在 grails 1.1 中不那么必要。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接