Hibernate OptimisticLockingFailureException在它应该的时候不会抛出

时间:2013-09-05 02:24:13

标签: hibernate grails optimistic-locking grails-2.0.4

假设我有以下域类:

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有人知道为什么会这样吗?

1 个答案:

答案 0 :(得分:0)

version是域类的属性(而不是字段),实际上定义为访问方法getVersion()。在version中定义了{{1>}的设置器。

对于脚手架控制器,虽然检查/验证是手动完成的,但是没有手动设置DefaultGrailsDomainClass属性的地方。当会话version遇到版本不匹配时,乐观锁定由休眠处理,只有当第二个用户是脏读的受害者时才会发生不匹配。

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