Запрос с помощью 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
Единственный способ сделать это - запустить запрос за пределами текущей транзакции.