Lazy vs Eager Fetch in JPA: Key Differences and When to Use Each
Lazy fetch delays loading related entities until they are accessed, while Eager fetch loads all related entities immediately with the main entity. Lazy fetch improves performance by loading data only when needed, whereas eager fetch simplifies access but can cause unnecessary data loading.Quick Comparison
This table summarizes the main differences between Lazy and Eager fetch types in JPA.
| Factor | Lazy Fetch | Eager Fetch |
|---|---|---|
| Loading Time | Loads related data only when accessed | Loads related data immediately with main entity |
| Performance | Better for large or optional data | Can cause performance issues if data is large |
| Use Case | When related data is not always needed | When related data is always needed |
| Proxy Objects | Uses proxies to delay loading | No proxies, direct loading |
| Risk | Can cause LazyInitializationException if accessed outside session | No such risk, data always available |
| Complexity | Requires careful session management | Simpler to use but less efficient |
Key Differences
Lazy fetch means JPA will not load the related entities from the database until you actually try to use them in your code. It uses proxy objects as placeholders. This approach saves resources by avoiding unnecessary data loading, especially useful when related data is large or rarely needed.
In contrast, Eager fetch loads all related entities immediately when the main entity is fetched. This makes accessing related data straightforward without extra queries later, but it can slow down performance if the related data is large or not always required.
One important difference is that Lazy fetch can cause a LazyInitializationException if you try to access the related data outside the persistence context (like after the database session is closed). Eager fetch avoids this by loading everything upfront, but at the cost of potentially loading unnecessary data.
Code Comparison
Example of Lazy fetch in a JPA entity relationship:
import jakarta.persistence.*; import java.util.List; @Entity public class Author { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(fetch = FetchType.LAZY, mappedBy = "author") private List<Book> books; // getters and setters }
Eager Fetch Equivalent
Example of Eager fetch for the same relationship:
import jakarta.persistence.*; import java.util.List; @Entity public class Author { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(fetch = FetchType.EAGER, mappedBy = "author") private List<Book> books; // getters and setters }
When to Use Which
Choose Lazy fetch when related data is large, optional, or rarely needed to improve performance and reduce memory use. It is ideal for complex applications where loading everything upfront would be costly.
Choose Eager fetch when related data is always needed together with the main entity, and simplicity is more important than performance. This avoids extra queries and session management issues.
In general, prefer Lazy fetch for better control and efficiency, but use Eager fetch when you are sure the related data is always required immediately.