Обновляет ли HQL 2-й уровень кеша?

Собственные запросы очищают записи кэша второго уровня. Ответ на форуме спящего режима, которому 7 лет, говорит, что запросы на обновление HQL также очищают кеш второго уровня. Но верно ли это?

Так как запрос HQL содержит точные поля, которые необходимо обновить, и в какой сущности я думаю, что это не должно быть так сложно, как если бы вызывается обычный session.save(..).

Ответы

Ответ 1

Собственные запросы очищают записи кэша второго уровня.

  • Собственные запросы (на самом деле это только для встроенных вставок/удалений/обновлений, а не для запросов) являются недействительными записи кэша второго уровня для всех кешей (WHOLE CACHE). Я проверил это с текущей стабильной версией Hibernate: 4.1.9. Это разумно, потому что Hiberante не может знать, что было изменено в БД, поэтому единственным вариантом является аннулирование всего кеша второго уровня. Это может быть серьезной проблемой в некоторых системах, которые в значительной степени зависят от кеша второго уровня.

Существует хотя бы возможность указать, что из кэша второго уровня должно быть недействительным (или даже указать, что ничего не выведено из кеша). Посмотрите на замечательный пост в блоге http://www.link-intersystems.com/bin/view/Blog/Hibernate%27s+second+level+cache+and+native+queries, где это объясняется полностью.

Чтобы предотвратить Hibernate от недействительности чего-либо из кеша:

SQLQuery sqlQuery = session.createSQLQuery("ALTER SESSION SET NLS_COMP = 'BINARY'");
sqlQuery.addSynchronizedQuerySpace("");  
int updatedEntities = sqlQuery.executeUpdate();

Чтобы указать Hibernate сделать недействительным только кеш-объект Person:

SQLQuery sqlQuery = session.createSQLQuery("UPDATE PERSON SET ... WHERE ...");
sqlQuery.addSynchronizedEntityClass(Person.class);
int updatedEntities = sqlQuery.executeUpdate();

Ответ на форуме спячки, который составляет 7 лет, говорит, что HQL обновления также очищают кеш второго уровня. Но верно ли это?

  1. HQL делает недействительным только область кэша второго уровня, которая связана с сущностью, в которую вы вставляете некоторые вставки/обновления/удаления. Это имеет смысл, потому что Hibernate знает, на какие объекты влияет HQL, он может очистить только область кэша второго уровня для этого объекта.

Пример:

entityManager.createQuery("delete from Person p where p.id = 1").executeUpdate();

Это приведет к недействительности "только" кэша объектов Person.

Мне не известно о возможности предотвратить Hibernate от недействительности кеша второго уровня для конкретной сущности, когда дело доходит до HQL.

Ответ 2

Мы видели обновление HQL, очищающее кеш второго уровня при работе с Hibernate 3.2.x

Как простой способ проверить вашу индивидуальную настройку, выполните следующее:

http://narcanti.keyboardsamurais.de/hibernate-statistics-jsp-reloaded.html

Обратите внимание на эту страницу до и после выполнения транзакции обновления HQL...

Или собирайте статистику непосредственно в своем коде и/или используя JMX

http://docs.jboss.org/hibernate/core/3.5/reference/en/html/performance.html#performance-monitoring

Что касается улучшенного поведения, проект Hibernate может быть открыт для реализации патча:)