Как использовать свойство версии оптимистической блокировки Hibernate на внешнем интерфейсе? - PullRequest
12 голосов
/ 14 сентября 2009

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

<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);
}

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

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

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

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

Заранее спасибо за ответы!

- LES

1 Ответ

11 голосов
/ 15 сентября 2009

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

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

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

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

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