JPA - Merging Detached Entity State

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

The changes made to a detached entity (last tutorial) can be synchronized to the database by using EntityManager.merge(detachedEntity).

EntityManager.merge(newInstance) can also be used on a new entity instance which has a valid database id.

Calling this method on a removed entity (tutorial here) will throw IllegalArgumentException.

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

Example

The Entity

@Entity
public class Employee {
  @Id
  @GeneratedValue
  private Integer id;
  private String name;
  private String department;

  public Employee() {
  }

  public Employee(String name, String department) {
      this(null, name, department);
  }

  public Employee(Integer id, String name, String department) {
      this.name = name;
      this.department = department;
      this.id = id;
  }
    .............
}

Persisting, merging and loading

public class ExampleMain {

  static EntityManagerFactory emf =
          Persistence.createEntityManagerFactory("example-unit");

  public static void main(String[] args) {
      Employee employee = new Employee("Sara Dorsey", "Admin");
      persistEmployee(employee);
      //employee at this point is detached but still has database id
      employee.setDepartment("Account");
      //merging
      updateEmployee(employee);
      //loading
      Employee employee2 = loadEmployeeById(employee.getId());
      print("Employee loaded", employee2);
      //creating new updated instance
      Employee employee3 = new Employee(employee.getId(), employee.getName(), "Sales");
      //merging
      updateEmployee(employee3);
      //loading again
      Employee employee4 = loadEmployeeById(employee.getId());
      print("Employee loaded", employee4);

      emf.close();
  }

  private static Employee loadEmployeeById(int id) {
      System.out.println("-- loading employee by id --");
      EntityManager em = emf.createEntityManager();
      return em.find(Employee.class, id);
  }

  private static void updateEmployee(Employee employee) {
      System.out.println("-- merging employee --");
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.merge(employee);
      em.getTransaction().commit();
      print("Employee merged", employee);
  }

  private static void persistEmployee(Employee employee) {
      System.out.println("-- persisting employee --");
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.persist(employee);
      em.getTransaction().commit();
      em.close();
      print("Employee persisted", employee);
  }

  private static void print(String msg, Object... objects) {
      System.out.printf("%s: %s%n", msg, Arrays.asList(objects));
  }
}

Output

-- persisting employee --
Employee persisted: [Employee{id=1, name='Sara Dorsey', department='Admin'}]
-- merging employee --
Employee merged: [Employee{id=1, name='Sara Dorsey', department='Account'}]
-- loading employee by id --
Employee loaded: [Employee{id=1, name='Sara Dorsey', department='Account'}]
-- merging employee --
Employee merged: [Employee{id=1, name='Sara Dorsey', department='Sales'}]
-- loading employee by id --
Employee loaded: [Employee{id=1, name='Sara Dorsey', department='Sales'}]

Example Project

Dependencies and Technologies Used :

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

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

See Also