Введение
При разработке приложений, связанных с ORM, я уже сталкивался с ситуациями, когда производительность приложения падала по причине большого траффика к БД. Hibernate единственный ORM фреймворк, которые помогает преодолеть такие сложные ситуации с помощью кэширования. В этой статье я попытаюсь дать детальное описание этой функции.
Как работает кэш Hibernate?
В веб-приложениях , используя Hibernate, кэш на самом деле хранит данные уже загруженные из БД. Это помогает уменьшить трафик между нашим приложением и БД. Большинство случаев извлечения данных попадает на кэш. Всякий раз когда нужны новые данные, будет сделан запрос в БД. Поскольку время, необходимое для доступа к БД, больше по сравнению с временем доступа к кэшу, трафик будет уменьшен между приложением и БД. В кэше хранятся только данные, связанные с текущим запущенным приложением. Следовательно, кэш должен быть очищен всякий раз когда приложение изменяется. Давайте рассмотрим как это все делается ниже.
Hibernate использует следующие кэши для объектов:
- First-level cache (Кэш первого уровня): Он всегда связан с объектом Session. Это обязательный кэш, через который проходят все запросы. Hibernate использует этот кэш по умолчанию. Если у Вас возникла необходимость много раз обновлять объект, Hibernate пытается задержать выполенение этих обновлений насколько это возможно для уменьшения количества вызовов SQL UPDATE. Он завершает эту транзакцию только в конце транзакции.
- Second-level cache (Кэш второго уровня): Он всегда связан с объектом Session Factory. Это опциональный кэш. Кэш второго уровня создается на уровне session factory и доступен для использования во всех сессиях, которые создаются используя конкретную данную фабрику сессий. Кэш вторго уровня может быть сконфигурирован отдельно для каждого класса и коллекции и в основном отвечает за кэширование между сеансами. Это означает, что в момент когда session factory закроется, весь кэш связанный с ним очиститься и cache менеджер также закроется.
- Query Cache (Кэш запросов): Кэш запросов используется для кэширования результатов запроса. Когда кэш запроса включен, результаты запроса сохраняются вместе с комбинацией запросов и параметров вызова. Каждый раз запрос вызовет проверку на наличие результата у кэш менеджера. Если результаты найдены в кэше, они возвращаются, иначе инициализируется транзакция в БД.
- Любой сторонний кэш может быть использован в Hibernate. Предоставляется интерфейс
org.hibernate.cache.CacheProvider,
который должен быть имплементирован для использования стороннего провайдера кэша.
Стратегии конкурентности
Стратегия конкурентности это посредник, который отвечает за сохранение данных в кэше и получение их из кэша. Если Вы собираетесь использовать кэш второго уровня, Вы должны решить какую стартегию применять для сохраяемых классов и коллекций.
Read-only (Только чтение)
- Полезно для данных, которые часто читаются, но никогда не обновляются.
- Простая в использовании
- Лучшая производительность среди всех
- Безопасно для использования в кластере.
Пример для использования стратегии read-only.
<hibernate-mapping> <class name="Student" table="STUDENT"> <meta attribute="class-description"> This class contains the STUDENT detail. </meta> <cache usage="read-only"/> .... </class> .......... </hibernate-mapping>
Использование атрибута «read-only» сообщает Hibernate что нужно использовать стратегию read-only для заданного кэша.
Read-Write (Запись-чтение)
- Используется в случае, когда наши данные необходимо обновлять.
- Есть больше оверхеда чем при применении стратегии read-only
- Не используется если требуется уровнь изоляции Serializable
- В среде JTA, для получения JTA Transaction Manager мы должны заполнить свойство hibernate.transaction.manager_lookup_class
- Для использования в кластере имплементация кэша должна поддерживать блокировку.
Пример для использования данной стратегии:
<hibernate-mapping> <class name="Student" table="STUDENT"> <meta attribute="class-description"> This class contains the STUDENT detail. </meta> <cache usage="read-write"/> .... </class> .......... </hibernate-mapping>
Nonstrict read-write (Нестрогое чтение-запись)
- Необходимо использовать, если приложение редко обновляет данные
- Мы должны заполнить hibernate.transaction.manager_lookup_class для использования в JTA
- Транзакция завершается, когда вызывается Session.close() или Session.disconnect() в других средах (кроме JTA)
Пример:
<class name="abc.xyz" .... > <cache usage=" nonstrict-read-write"/> …. </class>
Transactional
Используйте эту стратегию для данных, которые в большинстве случаев читаются и также где является критичным предотвращение протухания данных в конкурирующих транзакциях, в редком случае обновления.
Имплементации кэша
Теперь мы поняли как выбрать стратегии, и надо выбрать провайдера кэша. Hibernate принуждает Вас выбрать единственного провайдера кэша на все приложение. Каждый провайдер кэша не совметсим с каждой стратегией. Hibernate подерживает следующие опенсорсные имлементации кэша: EHCache (Easy Hibernate Cache), OSCache (Open Symphony Cache), Swarm Cache, JBoss Tree Cache.
Давайте рассмотрим каждого:
EHCache (Easy Hibernate Cache)
- Быстрый, легковесный и легкий в использовании
- Поддерживает только стратегии read-only и read-write
- Поддерживает кэширование на диске и в памяти
- Не поддерживает кластеризацию
OSCache (Open Symphony Cache) (org.hibernate.cache.OSCacheProvider)
- Мощный и гибкий
- Поддерживает только стратегии read-only и read-write
- Поддерживает кэширование на диске и в памяти
- Обеспечивает базовую поддержку для кластеризации через JavaGroups или JMS
SwarmCache (org.hibernate.cache.SwarmCacheProvider)
- Кэширование основанное на кластеризации
- Поддерживает read-only стратегию или нетстрогое чтение-запись
- Подходит к приложениям, у которых количество операций чтения больше чем операций записи
TreeCache (org.hibernate.cache.TreeCacheProvider) из JBoss
- мощный, реплицируемый (синхронно или асинхронно) и транзакционный кэш
- полезный, когда нам нужно правильная транзакционная архитектура кэша
Следующая таблица совместимостей поможет Вам выбрать подходящую комбинацию.
Cache Provider | Read-Only | Nonstrict Read-Only | Read-Write | Transactional |
EHCache | Yes | Yes | Yes | |
OSCache | Yes | Yes | Yes | |
SwarmCache | Yes | Yes | ||
TreeCache | Yes | Yes |
Вывод
В этой статье мы рассмотрели что такое кэширование Hibernate, типы конкурентных стратегий. Мы также рассмотрели доступных провайдеров кэша и как их выбрать. Спасибо за внимание!