Ответ
Hibernate предоставляет многоуровневую систему кэширования для минимизации обращений к базе данных.
1. Кэш первого уровня (L1, Session Cache)
- Включен по умолчанию, привязан к объекту
Session(илиEntityManager). - Обеспечивает гарантию уникальности экземпляра сущности в рамках сессии.
- Жизненный цикл равен жизненному циклу сессии.
Session session = sessionFactory.openSession();
// Первый вызов -> запрос к БД, результат кладется в L1
User u1 = session.get(User.class, 1L);
// Второй вызов -> данные берутся из L1 кэша
User u2 = session.get(User.class, 1L);
assert u1 == u2; // true
session.close(); // Кэш очищается
2. Кэш второго уровня (L2, Second-Level Cache)
- Разделяемый кэш между разными сессиями.
- Требует явной настройки и внешнего провайдера (Ehcache, Infinispan, Hazelcast).
- Сущность должна быть помечена как кэшируемая.
@Entity
@Cacheable // JPA аннотация
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) // Стратегия Hibernate
public class Product { ... }
3. Кэш запросов (Query Cache)
- Кэширует результаты HQL/Criteria/JPA Query вместе с идентификаторами сущностей.
- Для работы требует включенного L2 кэша.
- Настраивается в конфигурации Hibernate и указывается для конкретного запроса.
Query query = session.createQuery("from User where active = true");
query.setCacheable(true); // Включение кэширования для этого запроса
List<User> users = query.list();
Применение: Кэширование наиболее эффективно для данных, которые часто читаются и редко изменяются (справочники, конфигурации).