Принудительный запрос Hibernate для доступа к базе данных - PullRequest
10 голосов
/ 13 сентября 2010

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

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

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

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

Ответы [ 4 ]

11 голосов
/ 13 сентября 2010

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

Короче говоря: отследить старое значение самостоятельно.

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

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

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

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

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

Либо

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

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

StatelessSession statelessSession = sessionFactory.openStatelessSession();
try {
    return statelessSession.get(Ticket.class, ticketKey, LockMode.READ)
} finally {
   statelessSession.close()
} 
2 голосов
/ 13 сентября 2010

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

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

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

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

1 голос
/ 13 сентября 2010

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

...