JPA - Efficiently Persisting @ManyToOne associations with proxy returned by EntityManager.getReference()

[Updated: Dec 3, 2017, Created: Dec 3, 2017]

In the last example, we saw how to efficiently use EntityManager.getReference() method, to persist @OneToOne relationship without loading the already existing target entity's fields from the database. Following example shows the same for @ManyToOne relationship.

Example

The Entities

@Entity
public class Employee {
  @Id
  @GeneratedValue
  private Integer id;
  private String name;
  @ManyToOne
  private Department department;
    .............
}
@Entity
public class Department {
  @Id
  @GeneratedValue
  private Integer id;
  private String name;
    .............
}

Using getReference() method

public class GetReferenceExample {

  public static void main(String[] args) {
      EntityManagerFactory emf = Persistence.createEntityManagerFactory("example-unit");
      try {
          persistDepartment(emf);
          persistEmployees(emf);
          allEmployeesQuery(emf);
      } finally {
          emf.close();
      }
  }

  private static void persistDepartment(EntityManagerFactory emf) {
      System.out.println("-- persisting department --");
      Department department = new Department();
      department.setName("Admin");
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.persist(department);
      em.getTransaction().commit();
      em.close();
      System.out.println("Department persisted: " + department);
  }

  private static void persistEmployees(EntityManagerFactory emf) {
      System.out.println("-- persisting employees --");

      EntityManager em = emf.createEntityManager();
      Department department = em.getReference(Department.class, 1);

      Employee employee1 = new Employee();
      employee1.setName("Joe");
      employee1.setDepartment(department);

      Employee employee2 = new Employee();
      employee2.setName("Jackie");
      employee2.setDepartment(department);

      em.getTransaction().begin();
      em.persist(employee1);
      em.persist(employee2);
      em.getTransaction().commit();
      em.close();
      System.out.println("Employee persisted: " + employee1);
      System.out.println("Employee persisted: " + employee2);
  }

  private static void allEmployeesQuery(EntityManagerFactory emf) {
      System.out.println("-- select all employee query --");
      EntityManager em = emf.createEntityManager();
      Query query = em.createQuery("select t from Employee t");
      List<Employee> resultList = query.getResultList();
      for (Employee employee : resultList) {
          System.out.println(employee + " " + employee.getDepartment());
      }
  }
}
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: create table Department (id integer not null, name varchar(255), primary key (id))
Hibernate: create table Employee (id integer not null, name varchar(255), department_id integer, primary key (id))
Hibernate: alter table Employee add constraint FK14tijxqry9ml17nk86sqfp561 foreign key (department_id) references Department
-- persisting department --
Hibernate: call next value for hibernate_sequence
Hibernate: insert into Department (name, id) values (?, ?)
Department persisted: Department{id=1, name='Admin'}
-- persisting employees --
Hibernate: call next value for hibernate_sequence
Hibernate: call next value for hibernate_sequence
Hibernate: insert into Employee (department_id, name, id) values (?, ?, ?)
Hibernate: insert into Employee (department_id, name, id) values (?, ?, ?)
Employee persisted: Employee{id=2, name='Joe'}
Employee persisted: Employee{id=3, name='Jackie'}
-- select all employee query --
Hibernate: select employee0_.id as id1_1_, employee0_.department_id as departme3_1_, employee0_.name as name2_1_ from Employee employee0_
Hibernate: select department0_.id as id1_0_0_, department0_.name as name2_0_0_ from Department department0_ where department0_.id=?
Employee{id=2, name='Joe'} Department{id=1, name='Admin'}
Employee{id=3, name='Jackie'} Department{id=1, name='Admin'}

As seen above in hibernate query logs, Department's fields were never loaded via 'select' statement during persisting employees (in persistEmployees() method) and only Department's id (the foreign key) was used to persist the association.

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.getReference() and @OneToOne Example Select All Download
  • get-reference-and-one-to-one-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
        • resources
          • META-INF

See Also