Как объяснить, что такое персистентный контекст в JPA
Что проверяют
Понимаете ли вы, что между вашим кодом и базой стоит кеш с отслеживанием изменений, и знаете ли, откуда берутся его сюрпризы.
Как отвечать
Контекст сохраняемости это область, в которой JPA управляет сущностями. Обычно он живёт в пределах транзакции и делает три вещи.
Кеш первого уровня: в пределах контекста одна и та же строка возвращается одним и тем же объектом. Повторный поиск по идентификатору не пойдёт в базу, а сравнение через == для двух выборок даст истину.
Отслеживание изменений: при загрузке сохраняется снимок значений, а перед фиксацией контекст сравнивает текущее состояние со снимком и сам генерирует UPDATE. Поэтому вызывать save для управляемой сущности не нужно, достаточно поменять поле внутри транзакции.
Состояния сущности стоит перечислить: новая (ещё не связана с контекстом), управляемая (в контексте, изменения отслеживаются), отсоединённая (контекст закрыт), удалённая.
Дальше о том, ради чего вопрос и задают, о практических следствиях:
- сброс в базу происходит перед фиксацией, а также перед запросом, который может затронуть изменённые данные. Отсюда неожиданные
UPDATEв середине метода; - ленивые связи доступны только внутри контекста: обращение после закрытия даёт
LazyInitializationException. Лечится загрузкой заранее (join fetch, граф сущностей), а не открытием сессии на весь запрос; - контекст растёт: массовая обработка в одной транзакции копит тысячи управляемых объектов и снимков, поэтому её дробят и вызывают очистку;
- отсоединённые объекты из веб-запроса нужно присоединять, иначе изменения не сохранятся.
Где спотыкаются
Считают, что без явного вызова сохранения ничего не запишется.
Ловят исключение ленивой загрузки и лечат его переводом всех связей в жадные, получая тяжёлые запросы.
Держат одну транзакцию на всю пакетную обработку и упираются в память.