Подтвердить что ты не робот

Как использовать свойство оптимизированной блокировки Hibernate на передней панели?

Оптимистическая блокировка с использованием атрибута version для объекта работает отлично и легко реализуется:

<version property="VERSION" type="int" column="EX_VERSION" />

Объект имеет свойство следующего типа:

private int VERSION;
public int getVERSION() { return VERSION; }
public void setVERSION(int VERSION) { this.VERSION = VERSION; }

До сих пор так хорошо. Теперь методы службы возвращают объект передачи данных (DTO) для объекта выше, который отображаются в HTML. Для страниц обновлений атрибут VERSION хранится в скрытом поле HTML и отправляется с формой.

Цель состоит в том, чтобы использовать свойство version, чтобы убедиться, что обновление пользователя не сработает, если отображаемая информация сопровождается старой версией.

Контроллер отвечает на запрос обновления пользователей, вызывая метод службы с DTO, содержащий обновленную информацию (включая свойство версии), а метод службы, в свою очередь, использует объект доступа к данным (DAO) для сохранения изменений:

public void update(SimpleDTO dto) {
    SimplyEntity entity = getSimpleDao().load(dto.getId());
    copyProperties(dto, entity); // all properties, including VERSION copied to entity
    getSimpleDao().update(entity);
}

Проблема заключается в том, что свойство version, скопированное в объект copyProperties (...), не поддерживается Hibernate. Я проследил причину на следующем форуме: https://forum.hibernate.org/viewtopic.php?f=1&t=955893&p=2418068

Вкратце, когда вызывается load(), Hibernate кэширует свойство версии в кеше сеанса, и не имеет значения, для чего впоследствии оно изменилось. Я согласен с тем, что это правильное поведение, но мне поручено Bosses передать версию через свойство HTML-формы (если для этого есть лучший образец, я бы хотел его услышать).

Одно из решений, которое я изучаю сейчас, - это выдворить сущность из сеанса после того, как она была установлена ​​с помощью hibernateTemplate.evict(simpleEntity) до того, как произойдет обновление. Я надеюсь, что это сработает, но это не кажется эффективным.

Я хотел бы попросить Hibernate проверить свойство версии на самом экземпляре, а не только на кеш сеанса.

Заранее благодарим за ответы!

- LES

4b9b3361

Ответ 1

Вам нужно действительно использовать DTO? У вас не было бы этой проблемы, если бы вы проходили фактическую сущность вокруг - и вам не пришлось бы снова загружать объект, что не очень хорошо для производительности.

Но даже если у вас есть законная причина использовать DTO, я не совсем понимаю, почему вы пытаетесь обновить номер версии на своей недавно перезагруженной сущности до сохранения. Подумайте о возможных сценариях в вашем рабочем процессе:

  • Объект загружается изначально, имеет версию = V1
  • Передается в DTO, который переходит в UI, возвращается и готов к сохранению.
  • Объект загружается снова, имеет версию = V2

Теперь у вас есть две возможности:

  • V1 == V2. Peachy, вам не нужно ничего делать.
  • V1 меньше, чем V2, т.е. объект был обновлен кем-то еще во время редактирования. Нет никаких оснований пытаться установить версию на V1 и попытаться сохранить, потому что сохранение завершится неудачно. Вы можете либо сохранить его с помощью V2 (таким образом, переопределив изменения кого-то), либо выполнить сбой (без использования Hibernate).