Запрос с помощью Hibernate для доступа к базе данных

Я загрузил объект в свою транзакцию и изменил свойство этого объекта. Сделка еще не совершена. Теперь я хотел бы получить исходное значение измененного свойства.

Я пробовал с запросом HQL, например select p.property from Person p where p.id = 1 с идентификатором объекта, загруженного в транзакцию.

Я установил query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); перед выполнением запроса. Но успеха нет. Hibernate возвращает значение, указанное в текущей транзакции, а не в базе данных.

Есть ли способ обойти это?

Ответ 1

Я загрузил объект в свою транзакцию и изменил свойство этого объекта. Сделка еще не совершена. Теперь я хотел бы получить исходное значение измененного свойства.

Вкратце: сначала проследите старое значение.

Я пробовал с запросом HQL, например select p.property от Person p, где p.id = 1 с идентификатором объекта, загруженного в транзакцию.

Hibernate загружает уникальную версию объекта в сеанс (кеш первого уровня) для данного идентификатора базы данных. Это не сработает.

Я установил query.setHint( "org.hibernate.cacheMode", CacheMode.IGNORE); перед выполнением запроса.

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

Есть ли способ обойти это?

Либо

  • используйте session.refresh(), чтобы принудительно перезагрузить вашу сущность (и вы потеряете изменения).
  • сохраните предыдущее значение, как изначально упомянуто.
  • вызывать службу, выполняющую запрос в другой транзакции.

Ответ 2

Для меня работал StatelessSession.

StatelessSession statelessSession = sessionFactory.openStatelessSession();
try {
    return statelessSession.get(Ticket.class, ticketKey, LockMode.READ)
} finally {
   statelessSession.close()
} 

Ответ 3

Это может помочь:

Если вы хотите заставить кеш запросов обновить один из его регионов (не обращайте внимания на любые сохраненные в кеше результаты там) вы можете использовать org.hibernate.Query.setCacheMode(CacheMode.REFRESH). В сочетании с регионом вы определены для данного запроса, Спящий режим выборочно принудительно результаты, кэшированные в этом конкретном регион, который должен быть обновлен. Это особенно полезно в тех случаях, когда базовые данные могут быть обновлены через отдельный процесс и более эффективная альтернатива крупным партиям выселение региона через org.hibernate.SessionFactory.evictQueries().

(Из http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html, раздел 20.4.2).

Однако он предназначен для использования, когда другой процесс обновляет БД и должен использоваться с осторожностью. Ваш случай отличается. Поскольку этот метод встречается вне любой транзакции, вы должны быть уверены, что он не противоречит вашему дизайну. Возможно, вы можете реорганизовать поток вызовов, чтобы избежать этого поведения, и получить поле из другого источника или до того, как произойдет изменение в кеше...

Ответ 4

Единственный способ сделать это - запустить запрос за пределами текущей транзакции.