Как сделать сущность в состоянии detached?
Что проверяют
Знаете ли вы жизненный цикл сущности в JPA и понимаете ли, чем detached отличается от managed на практике. Почти всегда следом спрашивают, как вернуть такую сущность обратно и откуда берётся LazyInitializationException.
Как отвечать
Назовите четыре состояния: transient (new), managed, detached и removed. Detached это объект с идентификатором, который есть в базе, но persistence context за ним уже не следит: изменения не попадут в базу при flush, ленивые связи не загрузятся.
Способы получить detached:
entityManager.detach(entity): отсоединить одну сущность. Несброшенные изменения этой сущности при этом теряются, поэтому перед detach часто нуженflush();entityManager.clear(): отсоединить всё. Типичный приём в пакетной обработке:flush()иclear()каждые N записей, чтобы контекст не рос;- закрытие контекста:
close()уEntityManagerили конец транзакции при transaction-scoped контексте. В Spring это выход из метода с@Transactional; - откат транзакции: управляемые сущности этого контекста становятся detached;
- сериализация: объект, прошедший через сеть или внешний кеш, приходит отсоединённым;
- Hibernate API:
session.evict(entity)делает то же, чтоdetach.
Проверить состояние помогает entityManager.contains(entity). Вернуть сущность в контекст можно через merge(): он копирует её состояние в управляемый экземпляр и возвращает его. Методы update() и saveOrUpdate() в Hibernate 6 объявлены устаревшими.
Зачем это нужно: память в батчах и защита от случайной записи правок через dirty checking.
Где спотыкаются
Думают, что merge() делает управляемым переданный объект. Он остаётся detached, управляемым становится возвращённый экземпляр, и дальше менять нужно именно его.
Лечат LazyInitializationException через FetchType.EAGER или полагаются на spring.jpa.open-in-view, который в Spring Boot включён по умолчанию. Правильнее загрузить нужное заранее: JOIN FETCH, @EntityGraph или проекция в DTO.
Забывают про каскады: detach распространяется на связи только с CascadeType.DETACH или ALL, и связанные сущности остаются в контексте.