Hibernate OptimisticLockingFailureException在';应该是的

Hibernate OptimisticLockingFailureException在';应该是的,hibernate,grails,optimistic-locking,grails-2.0.4,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"/> <

假设我有以下域类:

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>
我通过在两个不同的浏览器中打开相同的编辑页面来测试它。我在一个浏览器中执行
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。有人知道为什么会发生这种情况吗?

version
是域类的属性(而不是字段),它实际上定义为访问器方法
getVersion()
版本的setter在
DefaultGrailDomainClass
中定义

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


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

您是否也可以显示域类
Book
id)中的code>version,该属性在成功的
刷新时更新?我只是想知道为什么要实现锅炉板代码来更新版本?@dmahapatro:手动设置版本的目的是(我想)确保Hibernate检查浏览器中显示的版本。是的,这就是目的。Grails在搭建的控制器中执行此操作的方式是手动检查,但是
save()
调用也应该引发异常,但事实并非如此。同样,您可以显示域类吗?我提供的只是一个示例。不过,我可以告诉您的是,我的映射中没有version:false,并且version列正在正确更新。
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