JPA - Detaching an Entity Instance from the Persistence Context

[Updated: Dec 1, 2017, Created: Nov 21, 2017]

An entity becomes detached (unmanaged) on following actions:

  • after transaction commit/rollback
  • by calling EntityManager.detach(entity)
  • by clearing the persistence context with EntityManager.clear()
  • by closing an entity manager with EntityManager.close()
  • serializing or sending an entity remotely (pass by value).

Changes to a detached entity (changing fields, removing, refreshing etc) will not be synchronized to the database state.

A detached entity still has the database identity.

EntityManager.detach() method is cascaded to entities referenced by this entity if the attribute cascade=ALL or cascade=DETACH are used (check out cascading tutorial).

Example

The Entity

@Entity
public class Employee {
  @Id
  @GeneratedValue
  private long id;
  private String name;
  private String dept;
    .............
}

Persisting and loading

public class ExampleMain {

  public static void main(String[] args) throws Exception {
      EntityManagerFactory emf =
              Persistence.createEntityManagerFactory("example-unit");
      try {
          persistEntity(emf);
          loadEntity(emf);
      } finally {
          emf.close();
      }
  }

  private static void persistEntity(EntityManagerFactory emf) throws Exception {
      Employee e = new Employee();
      e.setName("Jackie");
      e.setDept("Account");
      System.out.println("-- Persisting entity --");
      System.out.println(e);
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.persist(e);
      e.setDept("Admin");
      //after commit entity will become detached
      em.getTransaction().commit();
      em.close();
      //this will not be synchronized to database
      e.setDept("IT");
  }

  private static void loadEntity(EntityManagerFactory emf) {
      System.out.println("-- Loading entities --");
      EntityManager em = emf.createEntityManager();
      List<Employee> entityAList = em.createQuery("Select t from Employee t")
                                     .getResultList();
      entityAList.forEach(System.out::println);
      em.close();
  }
}

Output

-- Persisting entity --
Employee{id=0, name='Jackie', dept='Account'}
-- Loading entities --
Employee{id=1, name='Jackie', dept='Admin'}

As seen above, the changes which are made to Employee entity after the transaction commit, are not synchronized to the database.

Using detach() method

public class ExampleMain2 {

  public static void main(String[] args) throws Exception {
      EntityManagerFactory emf =
              Persistence.createEntityManagerFactory("example-unit");
      try {
          persistEntity(emf);
          loadEntity(emf);
      } finally {
          emf.close();
      }
  }

  private static void persistEntity(EntityManagerFactory emf) throws Exception {
      Employee e = new Employee();
      e.setName("Jackie");
      e.setDept("Account");
      System.out.println("-- Persisting entity --");
      System.out.println(e);

      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.persist(e);
      //need flush before detaching so changes made so far will
      //be synchronized to the database
      em.flush();
      //manually detaching
      em.detach(e);
      //this will not synchronized to the database
      e.setDept("Admin");
      em.getTransaction().commit();
      em.close();
  }

  private static void loadEntity(EntityManagerFactory emf) {
      System.out.println("-- Loading entities --");
      EntityManager em = emf.createEntityManager();
      List<Employee> entityAList = em.createQuery("Select t from Employee t")
                                     .getResultList();
      entityAList.forEach(System.out::println);
      em.close();
  }
}

Output

-- Persisting entity --
Employee{id=0, name='Jackie', dept='Account'}
-- Loading entities --
Employee{id=1, name='Jackie', dept='Account'}

As seen above, changes made to Employee entity after invoking detach() are not synchronized to the database.

Example Project

Dependencies and Technologies Used :

  • hibernate-core 5.2.8.Final: The core O/RM functionality as provided by Hibernate.
  • h2 1.4.193: H2 Database Engine.
  • JDK 1.8
  • Maven 3.3.9

EntityManager#detach() Example Select All Download
  • detach-entities-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
        • resources
          • META-INF

See Also