Ответ
Да. Hibernate предоставляет трехуровневую систему кэширования.
1. Кэш первого уровня (L1 Cache, Session Cache)
- Включен по умолчанию, привязан к объекту
Session. - Жизненный цикл — длительность сессии. Пример:
Session session = sessionFactory.openSession(); User u1 = session.get(User.class, 1L); // Запрос к БД User u2 = session.get(User.class, 1L); // Данные берутся из L1 кэша session.close(); // Кэш очищается
2. Кэш второго уровня (L2 Cache)
- Разделяемый кэш между сессиями. Требует явной настройки провайдера (Ehcache, Infinispan).
- Конфигурация в
persistence.xml:<property name="hibernate.cache.use_second_level_cache" value="true"/> <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/> - Аннотирование сущности:
@Entity @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Product { ... }
3. Кэш запросов (Query Cache)
- Кэширует результаты или идентификаторы объектов для конкретного HQL/SQL-запроса с параметрами.
- Включение:
<property name="hibernate.cache.use_query_cache" value="true"/> - Использование в коде:
Query query = session.createQuery("from User where active = true"); query.setCacheable(true);
Важно: Кэш запросов эффективен только вместе с настроенным L2 кэшем.
Ответ 18+ 🔞
А, ну вот, классика жанра, блядь! Hibernate и его трехуровневый кэш — это как три слоя защиты от собственной тупости, когда ты каждый раз лезешь в базу, как последний распиздяй.
Смотри, как это работает, а то потом будешь охуевать, почему всё тормозит.
Первый уровень, он же L1, он же Session Cache Это твой личный, персональный кошель, привязанный к одной сессии. Включен всегда, нахуй, по умолчанию. Пока сессия жива — он живёт. Закрыл сессию — и кэш твой накрылся медным тазом.
Session session = sessionFactory.openSession();
User u1 = session.get(User.class, 1L); // Пиздуй в базу, делай запрос
User u2 = session.get(User.class, 1L); // А тут уже, ебать, не надо! Берётся из кэша L1, как тёплый пирожок.
session.close(); // Всё, пиздец кэшу. Очистили.
Проще говоря, чтобы два раза не ездить в БД за одним и тем же в рамках одной операции.
Второй уровень, L2 Cache — уже серьёзнее Это уже общага, блядь, разделяемый кэш между всеми сессиями. Чтобы он заработал, надо его явно включить и поставить какого-нибудь провайдера, типа Ehcache. Без этого — нихуя не будет.
Вот, смотри, как в persistence.xml колдовать:
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
А сущность, которую хочешь кэшировать, надо пометить, как ценную бумагу:
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product { ... }
Теперь Product будет жить в этом общем кэше, и разные сессии смогут им пользоваться, не дергая БД.
И наконец, Кэш Запросов (Query Cache)
А это, сука, самая хитрая жопа. Он кэширует не объекты, а результаты конкретных запросов с их параметрами. Хочешь, чтобы один и тот же SELECT ... WHERE active = true не выполнялся каждый раз? Вот он, твой выход.
Включается отдельно:
<property name="hibernate.cache.use_query_cache" value="true"/>
А в коде надо явно сказать запросу: «Да, дружок, будь кэшируемым».
Query query = session.createQuery("from User where active = true");
query.setCacheable(true); // Вот этот волшебный пендель
Но главный подвох, ёпта! Кэш запросов — это пиздопроебибна, если у тебя не включен L2 кэш. Он нихуя не будет работать в одиночку, это как пытаться завести машину без бензина. Сначала настрой L2, а потом уже играйся с запросами.
Вот так вот, коротко и без лишней ебли. Настраивай, тестируй, смотри, что где тормозит, и не превращай кэш в свалку, а то получишь овердохуища проблем с согласованностью данных.