Зачем нужны кэши первого и второго уровня в Hibernate
Что проверяют
Различаете ли вы кэш сессии и общий кэш приложения, и понимаете ли, где второй опасен.
Как отвечать
Кэш первого уровня это контекст персистентности, то есть сама сессия. Он включён всегда и отключить его нельзя. В пределах одной сессии повторный find по тому же идентификатору не идёт в базу, а возвращает уже загруженный объект. Он же обеспечивает тождественность (одна сущность это один объект в пределах сессии) и отслеживание изменений: при сбросе Hibernate сам находит изменённые поля и генерирует UPDATE.
Кэш второго уровня общий для всех сессий и живёт на уровне фабрики сессий, то есть приложения. Включается явно и требует провайдера (Ehcache, Caffeine, Hazelcast) плюс аннотации @Cache на сущности. Смысл в том, чтобы редко меняющиеся справочники не читались из базы каждой сессией.
Рядом есть кэш запросов, который хранит не сущности, а списки идентификаторов по конкретному запросу с параметрами. Его включают отдельно и осторожно: он инвалидируется при любом изменении задействованных таблиц, поэтому на часто меняющихся данных приносит больше вреда, чем пользы.
Главная опасность кэша второго уровня: он не знает об изменениях, сделанных мимо Hibernate. Прямой UPDATE из другого сервиса, миграция или запрос через JDBC оставят в кэше устаревшие данные. Отсюда правило: включать его для справочников, а не для оперативных сущностей, и обязательно задавать стратегию инвалидации.
Где спотыкаются
Не знают, что кэш первого уровня существует всегда.
Включают кэш второго уровня для часто изменяемых сущностей.
Забывают про изменения в обход Hibernate и получают расхождение данных.
Считают кэш запросов бесплатным ускорением.