12

控制器逻辑:

def updateObject() {

    Object o = Object.get(params.id as Long)

    o.otherObjects.clear()

    objectDataService.saveObject(o.id)

    OtherObject newObject = new OtherObject;

    o.addToOtherObjects(newObject)

    objectDataService.saveObject(o.id)

}

服务逻辑

def saveObject(long profileId) {
    o.save(flush:true)
}

发生什么了

在 90% 的情况下,这将起作用。

问题

ERROR errors.GrailsExceptionResolver  - StaleObjectStateException occurred when processing request: [GET] /controller/updateObject - parameters:
stuff[]: data
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1]. 
Stacktrace follows:
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1]

我已经阅读了相关问题,并找到了merge您在上面看到的电话。它解决了大约 50% 的案例,但不是全部。

4

3 回答 3

11

陈旧对象状态异常:

正如已经评论过这个例外。当在刷新(显式或隐式)期间会话中存在无效的版本化域对象时,版本号会被碰撞,但不会持久保存到数据库中。然后,当它再次变为有效并保存并刷新时,hibernate 认为它是陈旧的,因为版本号与数据库中的版本不匹配并抛出 StaleObjectStateException。

这可以解决。

  1. 您必须在更新之前找出版本值,如果它是 1,那么您必须使用程序进行更新。在特定的更新操作。
  2. 通过使用@version 注释。

关于@版本:

乐观锁定的版本号机制是通过 @Version 注释提供的。示例:@Version 注释

@Entity
public class Flight implements Serializable {
...
    @Version
    @Column(name="OPTLOCK")
    public Integer getVersion() { ... }
} 

在这里,version 属性映射到 OPTLOCK 列,实体管理器使用它来检测冲突更新,并防止丢失将被 last-commit-wins 策略覆盖的更新@version

有关 Grails 的更多详细信息,请参阅下面的链接,它具有 Git 中心代码。
测试 GRAILS-8937:HibernateOptimisticLockingFailureException

于 2014-09-03T13:25:16.487 回答
7

StaleObjectStateException可以在任何其他项目上自然发生每次两个并发事务加载相同的实体版本并且每个都更改该实体时,由于乐观锁定冲突失败,您最终会导致最后一个执行线程失败。

在您的情况下,在 JPA 边界之外有一个额外的调用,这可能会促进这个问题:

Object o = PObject.lock(profileId)

每个事务都是线程绑定的,并且发生在一个会话中,因此两个竞争线程将为同一个实体 ID 保留两个对象引用。乐观锁定目标可以在没有任何其他显式锁定机制的情况下有效地工作。

如果您将修改后的实体引用发送到saveObject版本,但仍然收到此异常,则意味着您很有可能两个竞争线程修改相同的实体。

在这种情况下,悲观锁会产生更好的结果,因为它涉及等待而不是乐观的快速失败方法

于 2014-09-02T19:42:56.743 回答
4

对我们来说,一些不同的方法最终解决了 StaleObjectException 定期发生的问题:

object = object.refresh()

检索对象后刷新对象解决了我们的大部分 StaleObjectExceptions。尤其是在有人可能从其他地方处理同一个对象并更改其某些成员的情况下(大多数问题来自集合成员)。

整体项目稳定性:

wrongly linked resources

我们在一个我们实际上并不需要的特定资源文件上有一个 404,因此忽略了一段时间。事实证明,丢失的文件会导致会话保持打开状态——从而左右制造 StaleObjects。

因此,作为对面临更多问题的任何人的提示(可能总是会出现一些 StaleObjects - 请参阅上面的答案) StaleObjectExceptions:确保所有资源都正确链接并且您的开发人员工具(Chrome F12)不会报告任何丢失的文件。

于 2014-11-23T21:34:21.573 回答