Кэширование Hibernate

Hibernate использует несколько механизмов с разной областью жизни. Они не взаимозаменяемы.

Первый уровень

Это обязательный Persistence Context. Он хранит managed-сущности в пределах EntityManager/Session и гарантирует идентичность объекта. После clear или закрытия контекста записи исчезают.

Второй уровень

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

При попадании в L2 Hibernate всё равно создаёт объект текущего контекста. Кэш не хранит «живой» managed-экземпляр между потоками.

Кэш запросов

Хранит не сущности, а результат запроса — обычно набор идентификаторов и scalar-значений. Для сущностей затем нужен L2 либо чтение таблицы. Его выгода зависит от стабильности параметров и частоты инвалидирования.

Стратегии конкуренции

  • READ_ONLY — данные не меняются через Hibernate;
  • NONSTRICT_READ_WRITE — допускается короткое окно устаревших данных;
  • READ_WRITE — координирует обновления, но не заменяет транзакции БД;
  • TRANSACTIONAL — требует транзакционного провайдера и инфраструктуры.

Поддержка зависит от Провайдеры кэша второго уровня Hibernate.

Когда L2 вреден

  • данные часто изменяются;
  • несколько приложений меняют таблицу вне механизма инвалидирования;
  • результат почти всегда уникален;
  • кэш скрывает неоптимальный SQL;
  • нет метрик hit/miss, размера и времени вытеснения.

Вопросы для повторения

  1. L1 и L2 одинаковы? Нет: L1 принадлежит контексту и обязателен, L2 общий и опционален.
  2. Кэш запросов хранит готовые сущности? Обычно нет, он хранит ключи или scalar-результаты.
  3. Заменяет ли L2 Redis? Нет, назначение и модель согласованности отличаются.
  4. Что произойдёт после bulk update? Контекст и кэш могут содержать устаревшие данные; нужна явная очистка/инвалидация.
  5. С чего начинать оптимизацию? С измерения SQL, плана и числа запросов, а не с включения кэша.

Связано: Hibernate, EntityManager, SQL запросы VS Hibernate.