【问题标题】:Hibernate OptimisticLockingFailureException not throwing when it's supposed toHibernate OptimisticLockingFailureException 在它应该抛出的时候没有抛出
【发布时间】:2013-09-05 12:53:23
【问题描述】:

假设我有以下域类:

class Book {
    String name
    // more properties here, but name is the only one relevant for this example
}

我想通过视图更新它的名称。我正在使用以下表单来更新它:

<g:form action="updateName" id="${book.id}">
    <g:hiddenField name="version"/>
    <g:textField name="name"/>
    ...
</g:form>

在控制器中,我使用以下逻辑:

def updateName() {
    println("IN UPDATENAME()")
    def book = Book.get(params.id)
    println("VERSION BEFORE ASSIGN: ${book.version})
    book.version = params.long('version')
    println("VERSION AFTER ASSIGN: ${book.version})
    book.name = params.name
    book.save(flush: true)
    ...
}

我通过在 2 个不同的浏览器中打开相同的编辑页面来测试它。我在一个浏览器中执行updateName,然后是另一个浏览器。第二个updateName 应该抛出一个OptimisticLockingFailureException,但事实并非如此。

我启用了 SQL 输出,这是我在日志中得到的:

IN UPDATENAME()
VERSION BEFORE ASSIGN: 0
VERSION AFTER ASSIGN: 0
update book set version=?, name=? where id=? and version=?
binding parameter [1] as [BIGINT] - 1
binding parameter [2] as [STRING] - 'abc123'
binding parameter [3] as [BIGINT] - 1
binding parameter [4] as [BIGINT] - 0

IN UPDATENAME()
VERSION BEFORE ASSIGN: 1
VERSION AFTER ASSIGN: 0
update book set version=?, name=? where id=? and version=?
binding parameter [1] as [BIGINT] - 1
binding parameter [2] as [STRING] - 'def456'
binding parameter [3] as [BIGINT] - 1
binding parameter [4] as [BIGINT] - 1

换句话说,在第二次调用中,我能够成功地将版本从 1 分配到 0,这应该导致异常,但由于某种原因,SQL 调用仍然错误地检查版本 = 1 而不是 0 . 有人知道为什么会这样吗?

【问题讨论】:

  • 你也可以显示域类Book 吗? version 在 GORM 提供的隐式持久性属性(如 id)中,它会在成功的 flush 上更新?我只是想知道您为什么要实施样板代码来更新版本?
  • @dmahapatro:手动设置版本的目的是(我想)确保 Hibernate 检查浏览器中显示的版本。
  • 是的,这就是目的。 Grails 在脚手架控制器中执行此操作的方式是手动检查,但 save() 调用也应该抛出异常,但事实并非如此。
  • 再次,你能显示域类吗?
  • 我提供的只是一个例子。不过我可以告诉你的是,我的映射中没有 version: false ,并且 version 列正在正确更新。

标签: hibernate grails optimistic-locking grails-2.0.4


【解决方案1】:

version 是域类的一个属性(而不是一个字段),它实际上被定义为一个访问器方法getVersion()No version 的设置器在 DefaultGrailsDomainClass 中定义。

在脚手架控制器的情况下,也没有手动设置 version 属性的位置,尽管检查/验证是手动完成的。当遇到版本不匹配时,hibernate 在会话 flush 期间会处理乐观锁定,并且仅当第二个用户是脏读的受害者时才会发生不匹配。

在您的情况下,您要么必须通过手动验证版本来获取脚手架控制器逻辑,要么必须依靠 Hibernate 来完成其工作,而不是手动操作版本,这是不可行的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-25
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 2022-06-19
    • 1970-01-01
    • 2022-06-11
    • 2019-05-21
    相关资源
    最近更新 更多