EntityManager find vs getReference method

EntityManager find vs getReference method

In JPA, the EntityManager interface provides various methods to interact with the persistence context. Two commonly used methods for retrieving entities are find() and getReference(). While both methods are used to obtain an entity, they have different behaviors and use cases.

EntityManager find vs getReference method

EntityManager.find()

  • Eager Loading :
    • find() immediately retrieves the entity from the database and returns it. This method is equivalent to executing a SELECT query.
  • Returns Entity :
    • It returns a managed entity instance that is fully populated with data from the database.
  • Non-Proxy :
    • The returned entity is not a proxy; it is the actual entity object.

EntityManager.getReference()

  • Lazy Loading :
    • getReference() returns a proxy (a lazily initialized placeholder) to the entity. The actual database retrieval happens only when a property of the entity is accessed.
  • Returns Proxy :
    • It returns a proxy instance, which will only be populated with data from the database when accessed.
  • Throws EntityNotFoundException :
    • If the entity does not exist in the database, getReference() will throw an EntityNotFoundException when the entity is accessed.

When to Use Which?

  • Use find() :
    • When you need the actual entity immediately.
    • When you are sure the entity exists and want to work with it right away.
  • Use getReference() :
    • When you want to defer the database access until necessary.
    • When you are managing relationships and want to set a reference to an entity without immediately loading it.

Example

Let’s demonstrate the usage of both methods with a simple example.

Step 1: Define the Entity
java
package com.example.demo.model;

import javax.persistence.*;

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // Constructors, getters, and setters

    public Person() {}

    public Person(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Step 2: Define the Repository
java
package com.example.demo.repository;

import com.example.demo.model.Person;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}

Step 3: Define the Service
java
package com.example.demo.service;

import com.example.demo.model.Person;
import com.example.demo.repository.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Service
public class PersonService {

    @Autowired
    private PersonRepository personRepository;

    @PersistenceContext
    private EntityManager entityManager;

    public Person findPerson(Long id) {
        return entityManager.find(Person.class, id);
    }

    public Person getPersonReference(Long id) {
        return entityManager.getReference(Person.class, id);
    }
}

Step 4: Define the Controller
java
package com.example.demo.controller;

import com.example.demo.model.Person;
import com.example.demo.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/persons")
public class PersonController {

    @Autowired
    private PersonService personService;

    @GetMapping("/find/{id}")
    public Person findPerson(@PathVariable Long id) {
        return personService.findPerson(id);
    }

    @GetMapping("/reference/{id}")
    public Person getPersonReference(@PathVariable Long id) {
        return personService.getPersonReference(id);
    }
}

Explanation of Example

  • Person Entity (Person.java) :
    • Defined as a JPA entity with an ID and a name.
  • PersonService (PersonService.java) :
    • Provides methods to retrieve a Person entity using both find() and getReference() methods.
  • PersonController (PersonController.java) :
    • Exposes endpoints to test the behavior of find() and getReference() methods.

Summary

  • find() :
    • Retrieves the actual entity immediately.
    • Returns a fully initialized entity.
  • getReference() :
    • Returns a proxy that defers database access until necessary.
    • Throws EntityNotFoundException if the entity does not exist when accessed.