Как изменить стратегию автоматического сохранения Hibernate - PullRequest
3 голосов
/ 22 мая 2010

Я только что заметил, что объекты Hibernate автоматически сохраняются в базе данных (или, по крайней мере, для кэширования), прежде чем я вызову любые методы save() или update(). Для меня это довольно странное поведение по умолчанию - но хорошо, пока я могу его отключить, все в порядке.

Проблема, с которой я столкнулся, заключается в том, что я хочу обновить состояние своей сущности (из состояния «1» в состояние «2») только в том случае, если сущность в базе данных все еще имеет состояние, в котором она находилась, когда я ее получал (состояние «1 «). Это необходимо для устранения проблем параллелизма, когда другой сервер обновляет этот же объект. По этой причине я создал пользовательский NamedQuery, который будет обновлять сущность, только если она находится в ожидаемом состоянии «1». Вот некоторый псевдокод:

// Get the entity
Entity item = dao.getEntity(); 
item.getState(); // == 1

// Update the entity
item.setState(2); // Here is the problem, this effectively changes the
                  // state of my entity breaking my query that verifies
                  // that state is still == 1.

dao.customUpdate(item); //Returns 0 rows changes since state != 1.

Как мне убедиться, что установщики не меняют состояние в кеш / дБ?

Ответы [ 2 ]

1 голос
/ 22 мая 2010

Hibernate имеет встроенную поддержку того, чего вы хотите достичь - он поддерживает оптимистическую блокировку с использованием идентификаторов версий или временных меток. Если вы пытаетесь сохранить объект, а базовые данные изменились, hibernate выдает исключение. Вы можете перехватить это исключение и обработать его при необходимости - игнорируйте обновление, повторите попытку или все, что имеет смысл.

См. Оптимистичный контроль параллелизма

РЕДАКТИРОВАТЬ: мне не ясно, как работает ваш запрос на обновление, но если вы хотите продолжить делать это вручную, вы можете исключить ваш объект из сеанса после его получения. Это дает вам снимок объекта, как это было во время извлечения, которое вы можете изменить независимо от базы данных / кэша. Вы можете передать его в свой пользовательский запрос на обновление в качестве одной стороны сравнения, а другой стороной будет постоянное значение. Когда запрос выбирает / обновляет объект, он будет перечитан из базы данных, а не из вашего выселенного объекта. Ваш запрос на обновление может затем сравнить это с вашим выселенным / измененным значением (переданным в качестве параметра), чтобы увидеть, следует ли выполнить обновление или нет.

См. Session.evict ()

0 голосов
/ 22 мая 2010

Вы должны установить режим сброса вашего сеанса. Таким образом, сущности сеанса будут сохраняться только после выполнения сеанса # flush ();

Если вы хотите обновить кэш сеанса или базу данных, выполните что-то вроде этого:

Bean bean = session.get(Bean.class, bean.getId());
session.setFlushMode(FlushMode.COMMIT);
// Make some changes to bean object.
Bean bean2 = session.get(Bean.class, bean.getId());
Assert.assertFalse(bean.equals(bean1)); // Assuming equals and hashcode are implemented
...