Hibernate Кэш первого уровня против Query Cache

Отличается ли кеш первого уровня от кеша запросов в спящем режиме? Я видел статьи, упоминающие о первом уровне и кеше запросов, поэтому я запутался.

2 ответа

Решение

Кэш первого уровня включен по умолчанию и для каждой сессии. Кеш запросов по умолчанию не включен, используется несколькими сессиями и всегда должен использоваться вместе с кешем второго уровня.

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

hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=org.hibernate.cache.EhCacheProvider
hibernate.cache.use_query_cache=true

Да, это разные вещи. Как говорит Ли Чи Киам, кэш первого уровня включен по умолчанию, и его нельзя отключить. По сути, именно там Hibernate помещает извлеченные объекты в первый раз, поэтому второй запрос того же объекта не создает экземпляр нового объекта, даже избегает запроса, если он выполняется по идентификатору. Пример об этом здесь.

//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

session.getTransaction().commit();
HibernateUtil.shutdown();

Output:

Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource

Можно сказать, что кэш первого уровня - это Hibernate-реализация шаблона IdentityMap.

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

Как работает кеш запросов?

Предположим, у нас есть следующий критерий запроса:

session.createCriteria(Person.class)
    .add( Restrictions.eq("firstName", "Joey")
    ).setCacheable(true);

Кеш запросов концептуально выглядит как хэш-карта, где ключ состоит из текста запроса и значений параметров, а значение представляет собой список идентификаторов сущностей, соответствующих запросу.

*----------------------------------------------------------*
|                       Query Cache                        |                     
|----------------------------------------------------------|
| ["from Person where firstName=?", ["Joey"] ] -> [1, 2] ] |
*----------------------------------------------------------*

Поэтому в следующий раз, когда мы выполним тот же критерий запроса, Hibernate рассмотрит эту хеш-карту и решит, что люди с идентификаторами 1 и 2 соответствуют ограничениям. В этом случае вы бы избежали стоимости запроса (который в этом случае почти равен нулю, но может быть дорогим запросом с объединениями и т. Д.), Но вы все равно будете обращаться к базе данных для запроса лиц (теперь по идентификатору, что является очень быстро) для построения объектов Person. Кэш запросов часто используется с кэшем второго уровня, для которого требуется реализация третьей части, например Ehcache или infinispan.

Кэш второго уровня хранит данные сущностей, но НЕ сами сущности. Данные хранятся в "обезвоженном" формате, который выглядит как хэш-карта, где ключ - это идентификатор объекта, а значение - это список примитивных значений. Вот пример того, как выглядит содержимое кэша второго уровня:

*-----------------------------------------*
|          Person Data Cache              |
|-----------------------------------------|
| 1 -> [ "Joey" , "Q" , "Public" , null ] |
| 2 -> [ "Joey" , "D" , "Public" ,  1   ] |
| 3 -> [ "Sara" , "N" , "Public" ,  1   ] |
*-----------------------------------------*

Итак, кеш запросов даст нам идентификаторы 1 и 2, а затем Hibernate создаст объекты с необработанными данными в кеше второго уровня, который соответствует Person с id 1 и 2.

Кэш запросов и кэш второго уровня предназначены для объектов с большим количеством операций чтения и небольшим или нулевым обновлением. Потому что хорошо известна проблема несоответствия в каждом типе кеша. Поэтому Hibernate нужно будет сделать недействительным или обновить кэш (с включенной репликацией, если у вас есть кластерный кеш). Со многими обновлениями вы будете постоянно аннулировать кеш, и это принесет больше вреда, чем пользы.

Некоторые объяснения взяты из этого замечательного поста, и вы должны прочитать этот хороший ответ тоже.

Другие вопросы по тегам