Настраивали ли вы кэширование в Hibernate?

Ответ

Да. 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, а потом уже играйся с запросами.

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