🗃️ JPA Q37 / 63

What is the difference between find() and getReference() in JPA?

AI-Powered Answer ✓ Answered

In JPA, both EntityManager.find() and EntityManager.getReference() are used to retrieve an entity by its primary key. However, they differ significantly in their loading strategy, database interaction, and behavior when an entity does not exist.

EntityManager.find() Method

The find() method is used for immediate, eager loading of an entity. When you call find(), the EntityManager immediately attempts to retrieve the entity from the database. If the entity is found, it returns the actual entity object. If the entity with the given primary key does not exist, find() returns null.

java
User user = entityManager.find(User.class, 1L);
if (user != null) {
    System.out.println("User found: " + user.getName());
} else {
    System.out.println("User not found.");
}

EntityManager.getReference() Method

The getReference() method is used for lazy loading. It does not hit the database immediately. Instead, it returns a proxy (or a 'stub') of the entity without initializing its state. The actual database interaction occurs only when you access any persistent property of the entity (other than its identifier). If an entity with the given primary key does not exist in the database, getReference() throws an EntityNotFoundException when a persistent property is accessed for the first time.

java
try {
    User userRef = entityManager.getReference(User.class, 2L);
    // At this point, no DB call has been made yet.
    // The DB call happens when userRef.getName() is invoked.
    System.out.println("User reference obtained, name: " + userRef.getName());
} catch (EntityNotFoundException e) {
    System.out.println("User with ID 2 not found.");
}

Key Differences Summary

FeatureEntityManager.find()EntityManager.getReference()
Database InteractionImmediate database hit.Database hit only upon first access to a persistent property (lazy).
Return Value if Not FoundReturns null.Throws EntityNotFoundException when a persistent property is accessed.
Loading StrategyEager loading.Lazy loading.
Object TypeReturns the actual entity object.Returns a proxy (subclass) of the entity.
Use CaseWhen you need the entity data immediately or when the entity might not exist.When you only need to establish a relationship or when you are certain the entity exists to avoid unnecessary DB calls.

When to Use Each Method

  • Use EntityManager.find() when:
  • - You need to retrieve the actual entity data immediately.
  • - You are unsure if the entity with the given ID exists, as it gracefully handles non-existence by returning null.
  • - You are displaying entity details to a user.
  • Use EntityManager.getReference() when:
  • - You need to establish a relationship with another entity without loading its entire state (e.g., setting a foreign key).
  • - You are certain the entity with the given ID exists.
  • - You want to defer database loading until the entity's data is actually accessed, optimizing performance by avoiding unnecessary database calls.

Conclusion

The choice between find() and getReference() largely depends on the specific use case, particularly regarding when you need the entity's data and how you want to handle non-existent entities. find() provides immediate access and null-safety, while getReference() offers performance benefits through lazy loading when only a reference is needed.