EntityManager

EntityManager — основной интерфейс JPA для работы с Persistence Context. Он не просто отправляет запросы, а управляет состоянием сущностей в рамках единицы работы.

Основные операции

МетодСмысл
persist(entity)сделать новый объект managed; метод ничего не возвращает
find(Type.class, id)найти по ключу; обычно сразу обращается к контексту или БД
getReference(Type.class, id)получить ссылку-прокси без гарантии немедленного SQL
merge(entity)скопировать состояние detached-объекта в managed-экземпляр и вернуть его
remove(entity)пометить managed-сущность на удаление
flush()синхронизировать изменения с БД
clear()отсоединить все сущности
detach(entity)отсоединить одну сущность
refresh(entity)перечитать состояние из БД

Критическая деталь merge: переданный объект не становится managed.

Order managed = entityManager.merge(detached);
// дальше меняем managed, а не detached

Жизненный цикл и граница

В Spring EntityManager обычно предоставляется прокси, который направляет вызовы в контекст текущей транзакции. Хранить его в статическом поле или передавать между потоками нельзя.

После завершения контекста сущности становятся detached. Обращение к незагруженной ленивой связи тогда приводит к LazyInitializationException.

Запросы и flush

JPA может выполнить автоматический flush перед JPQL-запросом, чтобы запрос увидел изменения контекста. Режим COMMIT уменьшает такие синхронизации, но не отменяет flush перед фиксацией.

Вопросы для повторения

  1. Чем find отличается от getReference? find возвращает данные либо null; getReference может вернуть прокси и сообщить об отсутствии строки позже.
  2. Что возвращает merge? Managed-копию; исходный объект остаётся detached.
  3. persist немедленно делает INSERT? Не всегда; SQL часто откладывается до flush, хотя стратегия ключа может потребовать ранней вставки.
  4. Можно ли использовать один EntityManager в двух потоках? Нет.
  5. Что очищает clear? Весь persistence context; несинхронизированные изменения могут быть потеряны.

Связано: Жизненный цикл Entity в Hibernate, Transactional, LockModeType.