JPA - Efficiently Persisting @OneToOne association with the proxy returned by EntityManager.getReference()

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

The method EntityManager.getReference() can be useful, to initialize an associations like @ManyToOne or @OneToOne with already exiting target entity without loading it's fields from the database.

Example

Following example shows initializing and persisting @OneToOne relationship with getReference() method.

The Entities

@Entity
public class Employee {
  @Id
  @GeneratedValue
  private Integer id;
  private String name;
  @OneToOne
  private Task task;
    .............
}
@Entity
public class Task {
  @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 {
          persistTask(emf);
          persistEmployee(emf);
          allEmployeesQuery(emf);
      } finally {
          emf.close();
      }
  }

  private static void persistTask(EntityManagerFactory emf) {
      System.out.println("-- persisting Task --");
      Task task = new Task();
      task.setName("test task");
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.persist(task);
      em.getTransaction().commit();
      em.close();
      System.out.println("Task persisted: " + task);
  }

  private static void persistEmployee(EntityManagerFactory emf) {
      System.out.println("-- persisting employee --");
      Employee employee = new Employee();
      employee.setName("Joe");
      EntityManager em = emf.createEntityManager();
      Task task = em.getReference(Task.class, 1);
      employee.setTask(task);
      em.getTransaction().begin();
      em.persist(employee);
      em.getTransaction().commit();
      em.close();
      System.out.println("Employee persisted: " + employee);
  }

  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.getTask());
      }
  }
}
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: create table Employee (id integer not null, name varchar(255), task_id integer, primary key (id))
Hibernate: create table Task (id integer not null, name varchar(255), primary key (id))
Hibernate: alter table Employee add constraint FKknovwluxttletr14l9atj112y foreign key (task_id) references Task
-- persisting Task --
Hibernate: call next value for hibernate_sequence
Hibernate: insert into Task (name, id) values (?, ?)
Task persisted: Task{id=1, name='test task'}
-- persisting employee --
Hibernate: call next value for hibernate_sequence
Hibernate: insert into Employee (name, task_id, id) values (?, ?, ?)
Employee persisted: Employee{id=2, name='Joe'}
-- select all employee query --
Hibernate: select employee0_.id as id1_0_, employee0_.name as name2_0_, employee0_.task_id as task_id3_0_ from Employee employee0_
Hibernate: select task0_.id as id1_1_0_, task0_.name as name2_1_0_ from Task task0_ where task0_.id=?
Employee{id=2, name='Joe'} Task{id=1, name='test task'}

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

Check out next example of getReference() with @ManyToOne.

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