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, чтобы выполнять свою работу, вместо того, чтобы манипулировать версией вручную, что невозможно.

Другие вопросы по тегам