Какую роль играет кэширование в ORM (на примере Hibernate) и какие уровни кэша существуют?

Ответ

Кэширование в ORM минимизирует обращения к базе данных, сохраняя загруженные сущности и результаты запросов в памяти.

Основные преимущества:

  • Резкое повышение производительности для операций чтения, особенно при повторных обращениях к одним и тем же данным.
  • Снижение нагрузки на СУБД за счет сокращения количества выполняемых SQL-запросов.
  • Обеспечение консистентности в рамках сессии (кэш первого уровня).

Уровни кэширования в Hibernate:

Уровень Область видимости Назначение
Кэш 1-го уровня (L1) Сессия (Session) Автоматический. Гарантирует, что в рамках одной сессии загрузка сущности по идентификатору всегда возвращает один и тот же экземпляр объекта.
Кэш 2-го уровня (L2) Фабрика сессий (SessionFactory) Опциональный, общий для всех сессий. Требует явного включения и провайдера (Ehcache, Infinispan, Redis).
Кэш запросов Фабрика сессий (SessionFactory) Кэширует результаты часто выполняемых HQL/JPA-запросов или критериев. Работает только при включенном L2-кэше.

Пример настройки L2-кэша для сущности:

@Entity
@Cacheable // Активация кэширования для JPA
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) // Стратегия Hibernate
public class Product {
    @Id
    private Long id;
    private String name;
}

Важные аспекты:

  • Стратегии согласованности: READ_ONLY (только для неизменяемых данных), READ_WRITE, NONSTRICT_READ_WRITE, TRANSACTIONAL.
  • Инвалидация кэша – критически важна при изменении данных через другие приложения или прямые SQL-запросы. Требует настройки стратегий обновления или явного сброса.

Ответ 18+ 🔞

Да ты посмотри, какие штуки придумали, чтобы базу данных не ебашить почём зря! Кэширование в ORM — это типа такой хитрожопый способ не лазить в базу каждый раз, как дурак, а держать уже загруженные штуки прямо в памяти.

Что за плюсы, спросишь? Да овердохуищные:

  • Скорость пиздец как растёт, особенно если ты тупо раз за разом лезешь за одними и теми же данными.
  • База не обоссытся от запросов — нагрузка падает, потому что SQL-запросов становится меньше.
  • В рамках одной сессии всё чётко — кэш первого уровня следит, чтобы один и тот же объект тебе и возвращался.

А уровни кэширования в Hibernate, блядь, вот какие бывают:

Уровень Где живёт Зачем нужен
Кэш 1-го уровня (L1) Внутри сессии (Session) Работает сам, автоматом. Чтобы если ты в одной сессии дважды за одной хуйней полез, тебе один и тот же экземпляр вернули, а не два разных.
Кэш 2-го уровня (L2) На всю фабрику сессий (SessionFactory) Вот это уже поинтереснее. Общий для всех. Но его надо специально включать и какую-нибудь библиотеку-провайдер подсовывать (Ehcache, Infinispan, Redis).
Кэш запросов Тоже на фабрике (SessionFactory) Запоминает результаты твоих частых HQL-запросов. Но, внимание, ёпта, работает только если L2-кэш тоже включён!

Вот как, например, сущность пометить, чтобы её в L2-кэш пихали:

@Entity
@Cacheable // Говорим JPA: "Кэшируй это, блядь"
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) // А это Hibernate-у, со стратегией
public class Product {
    @Id
    private Long id;
    private String name;
}

А теперь, чувак, главное не обосраться:

  • Стратегии, блядь, выбери с умом: READ_ONLY (только для того, что не меняется), READ_WRITE, NONSTRICT_READ_WRITE, TRANSACTIONAL. Каждая — под свой случай.
  • Инвалидация кэша — вот где собака зарыта! Если данные меняются через другое приложение или прямой SQL-запрос, а кэш про это не знает — будет пиздец и рассинхрон. Надо либо стратегии правильно настраивать, либо кэш вручную сбрасывать. Иначе получишь старые данные, а потом будешь чесать репу, где ж ошибка.