Hibernate OptimisticLockingFailureException не выдает, когда он должен
Допустим, у меня есть следующий класс домена:
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 ответ
version
это свойство (а не поле) класса домена, которое фактически определяется как метод доступа getVersion()
, Нет установщика для version
определяется в DefaultGrailsDomainClass
,
В случае контроллера лесов, нет, где version
свойство устанавливается вручную, хотя проверка / проверка выполняется вручную. Оптимистическая блокировка обрабатывается в спящем режиме во время сеанса flush
когда встречается несоответствие в версии, и несоответствие происходит только в том случае, если второй пользователь является жертвой грязного чтения.
В вашем случае вы либо должны собрать логику контроллера scaffolded, проверив версию вручную, либо вы должны полагаться на Hibernate, чтобы выполнять свою работу, вместо того, чтобы манипулировать версией вручную, что невозможно.