Какие состояния входят в жизненный цикл сущности JPA?

«Какие состояния входят в жизненный цикл сущности JPA?» — вопрос из категории Hibernate, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Сущность (Entity) в JPA проходит через четыре основных состояния, определяемых ее связью с контекстом persistence (EntityManager):

Состояние Описание Связь с EntityManager Синхронизация с БД
New (Transient) Объект создан в памяти, но не является управляемой сущностью JPA. Нет Не отслеживается. Нет соответствия записи в БД.
Managed (Persistent) Объект ассоциирован с контекстом persistence. Да (привязан к EM) Автоматически. Изменения в объекте отслеживаются и будут синхронизированы с БД при коммите транзакции или вызове flush().
Detached Объект был в состоянии Managed, но его связь с EntityManager была разорвана. Нет (был привязан) Не отслеживается. Для обновления в БД его нужно снова перевести в состояние Managed (обычно через merge()).
Removed Объект помечен на удаление из базы данных. Да (привязан к EM) Будет удален из БД при коммите транзакции или вызове flush().

Переходы между состояниями:

  • New -> Managed: EntityManager.persist(entity)
  • Managed -> Detached: EntityManager.detach(entity), EntityManager.clear(), закрытие EntityManager.
  • Detached -> Managed: EntityManager.merge(entity) (создает или находит управляемую копию).
  • Managed -> Removed: EntityManager.remove(entity)
  • Removed -> New (после коммита): После удаления из БД объект становится New, если ссылка на него сохранена.

Пример на Java:

// 1. New (Transient)
Employee emp = new Employee("John Doe"); // Нет ID, нет связи с EM

// 2. Managed (Persistent)
entityManager.getTransaction().begin();
entityManager.persist(emp); // Теперь emp - управляемая сущность, будет вставлена в БД
emp.setName("Jane Doe"); // Изменение отслеживается! При коммите БД обновится.
entityManager.getTransaction().commit();

// 3. Detached
entityManager.detach(emp); // или entityManager.close();
emp.setName("New Name"); // Изменение НЕ синхронизируется с БД, т.к. состояние Detached.

// 4. Возврат в Managed (для обновления)
entityManager.getTransaction().begin();
Employee mergedEmp = entityManager.merge(emp); // mergedEmp - новая управляемая копия
entityManager.getTransaction().commit(); // Изменения mergedEmp сохранятся в БД