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.
Table of Contents
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.