Как правильно заблокировать и перезагрузить объект - PullRequest
6 голосов
/ 14 июля 2011

В моем веб-приложении у меня есть несколько потоков, которые могут одновременно обращаться к одним и тем же данным, поэтому я решил реализовать оптимистическую (версионную) и пессимистическую блокировки с помощью Hibernate.

В настоящее время я использую следующий шаблон для блокировки сущности и выполнения операций записи в нее (с помощью диспетчера транзакций Springs и разграничения транзакций с помощью @Transactional):

@Transactional
public void doSomething(entity) {
    session.lock(entity, LockMode.UPGRADE);
    session.refresh(entity);

    // I change the entity itself as well as entites in a relationship.
    entity.setBar(...);
    for(Child childEntity : entity.getChildren()) {
        childEntity.setFoo(...);
    }
}

Однако иногда я получаюStaleObjectException когда @Transactional мигает, что говорит мне, что ChildEntity был изменен одновременно и теперь имеет неправильную версию.

Я предполагаю, что неправильно обновляет entity и его дочерние элементы так что я работаю с устаревшими данными.Может кто-нибудь указать, как этого добиться?Некоторые мысли обо мне включали очистку контекста постоянства (сеанс) или повторный вызов session.lock(entity, LockMode.READ), но я не уверен, что здесь правильно.

Спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 30 апреля 2013

Вы можете взглянуть на этот Hibernate-Issue: LockMode.Upgrade не обновляет значения сущностей .

Короче говоря: Hibernat НЕ выполняет выбор после успешногоблокировка, если данный объект уже был предварительно загружен.Вам нужно вызвать обновление для сущности для себя после того, как вы получили блокировку.

0 голосов
/ 14 июля 2011

Почему вы делаете «LockMode.UPGRADE» и оптимистическую блокировку живыми вместе?Похоже на противоречивые вещи.

Hibernate никогда не блокирует объекты в памяти и всегда использует механизм блокировки базы данных.Кроме того, «если запрошенный режим блокировки не поддерживается базой данных, Hibernate использует соответствующий альтернативный режим вместо исключения. Это обеспечивает переносимость приложений».Это означает, что если ваша база данных не поддерживает SELECT ... FOR UPDATE, скорее всего, вы получите эти исключения.

Другая возможная причина в том, что вы не использовали "org.hibernate.annotations.CascadeType.LOCK "для детей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...