Gymterview
junior

Что такое кэш первого уровня (L1 Cache)?

Кэш первого уровня (L1 Cache) — это Persistence Context, привязанный к Session (или EntityManager). Это обязательный кэш, который нельзя отключить.

Как работает

Пример
@Transactional
public void example() {
    // Запрос к БД — объект помещается в L1 Cache
    User user1 = entityManager.find(User.class, 1L);  // SQL SELECT

    // Повторный запрос — объект берётся из L1 Cache, без SQL
    User user2 = entityManager.find(User.class, 1L);  // НЕТ SQL

    // Гарантия идентичности
    assert user1 == user2;  // true — один и тот же объект

    // Изменение объекта — Dirty Checking отслеживает
    user1.setName("New Name");
    // При commit/flush → UPDATE users SET name = 'New Name' WHERE id = 1
}
// L1 Cache уничтожается при закрытии Session/транзакции

Свойства L1 Cache

  • Привязан к Session, живёт в рамках одной транзакции
  • Хранит управляемые (Persistent) сущности
  • Гарантирует identity — один ID → один объект в рамках Session
  • Обеспечивает Dirty Checking — автоматическое обнаружение изменений
  • Write-behind — SQL-запросы откладываются до flush

Очистка L1 Cache

Пример
entityManager.clear();          // очистить весь L1 Cache
entityManager.detach(user);     // убрать конкретную сущность из кэша

Важное

  • L1 Cache = Persistence Context = Session — это одно и то же
  • Нельзя отключить — это фундаментальная часть Hibernate
  • Живёт в рамках одной транзакции (@Transactional)
  • Гарантирует, что два вызова find(User.class, 1L) вернут один и тот же Java-объект

Частые ошибки

  • Загрузка слишком большого количества сущностей — все загруженные сущности хранятся в L1 Cache; 100K сущностей → OutOfMemoryError
  • Не использовать clear() при batch-обработке — при вставке миллиона записей L1 Cache переполняется
  • Ожидать L1 Cache между транзакциями — каждая транзакция имеет свой Persistence Context; кэш не переживает транзакцию

Как используется в 2026

  • L1 Cache работает прозрачно, разработчик взаимодействует с ним косвенно
  • Для batch-операций: clear() каждые N записей — обязательный паттерн
  • Spring @Transactional(readOnly = true) оптимизирует L1 Cache — отключает Dirty Checking

На собеседовании: ключевое — L1 Cache = Persistence Context = Session. Он обязателен и живёт в рамках одной транзакции. Интервьюер может спросить «что будет, если дважды вызвать find() с одинаковым ID?» — ответ: второй вызов вернёт тот же объект из кэша без SQL. Упомяните проблему OOM при batch-обработке и решение через clear().