What is the difference between eager and lazy loading in JPA/Hibernate?
Understand eager vs lazy loading in JPA and Hibernate: default fetch types, proxies, LazyInitializationException, and how to avoid the N+1 query problem.
Expected Interview Answer
Eager loading fetches an entity's associations immediately along with the parent in the same query, while lazy loading defers fetching each association until it is actually accessed, issuing a separate query at that moment.
In JPA the fetch type is controlled by the FetchType enum: @OneToMany and @ManyToMany default to LAZY, whereas @ManyToOne and @OneToOne default to EAGER. Lazy loading relies on Hibernate proxies and requires an open persistence context, so touching a lazy association after the session closes throws LazyInitializationException. Eager loading avoids that but can pull far more data than needed and cause N+1 query problems when applied across collections.
- Lazy loading reduces initial query size and memory footprint
- Eager loading guarantees data is present outside the session
- Fetch strategy can be tuned per use case with join fetch or entity graphs
- Prevents loading unused associations on hot paths
- Helps control the N+1 select problem when chosen deliberately
AI Mentor Explanation
Eager loading is like a team manager who, the moment a squad is named, immediately prints every player's full medical file, contract, and travel plan whether or not the match needs them. Lazy loading is the physio who only pulls a specific player's file when that player is actually being assessed, saving effort until the detail is genuinely required on the field.
Step-by-Step Explanation
Step 1
Know the defaults
@ManyToOne and @OneToOne are EAGER by default; @OneToMany and @ManyToMany are LAZY.
Step 2
Declare the fetch type
Set fetch = FetchType.LAZY or FetchType.EAGER on the association annotation to override the default.
Step 3
Keep the session open
Access lazy associations within a transaction or open persistence context, or they fail after the session closes.
Step 4
Fetch what you need
Use JOIN FETCH, @EntityGraph, or a projection to eagerly pull only the associations a given query requires.
Step 5
Watch for N+1
Profile generated SQL; a loop touching lazy collections issues one query per parent, so batch or join-fetch instead.
What Interviewer Expects
- Correct default fetch types per association annotation
- Understanding of Hibernate proxies and the persistence context
- Knowing what causes LazyInitializationException
- Awareness of the N+1 select problem
- How to override fetching with JOIN FETCH or entity graphs
Common Mistakes
- Claiming all associations are lazy by default
- Making every association EAGER to avoid exceptions
- Accessing lazy fields outside an open session
- Ignoring the N+1 query problem eager collections can cause
- Confusing FetchType with cascade type
Best Answer (HR Friendly)
“Eager loading grabs all the related data at once when you load a record, while lazy loading waits and fetches related data only when you actually need it. Lazy is lighter by default, but you have to make sure the connection is still open when you reach for that extra data.”
Code Example
@Entity
public class Author {
@Id
private Long id;
// collections are LAZY by default
@OneToMany(mappedBy = "author", fetch = FetchType.LAZY)
private List<Book> books;
}
// Override lazy loading for a specific query to avoid N+1
@Query("SELECT a FROM Author a JOIN FETCH a.books WHERE a.id = :id")
Author findWithBooks(@Param("id") Long id);Follow-up Questions
- What causes a LazyInitializationException and how do you fix it?
- Explain the N+1 select problem and ways to solve it.
- How does @EntityGraph change fetching behavior?
- Why can EAGER fetching hurt performance on collections?
- What is the difference between FetchType and CascadeType?
MCQ Practice
1. What is the default fetch type for a @OneToMany association in JPA?
Collection associations (@OneToMany and @ManyToMany) default to LAZY, whereas @ManyToOne and @OneToOne default to EAGER.
2. Which exception occurs when a lazy association is accessed after the session is closed?
Hibernate throws LazyInitializationException because the proxy needs an open persistence context to load the data.
3. Which technique best avoids the N+1 problem when reading a collection?
JOIN FETCH or an entity graph loads the parent and its collection in a single query, eliminating the per-parent extra selects.
Flash Cards
Default fetch for @ManyToOne? — EAGER — the associated single entity is loaded with its parent.
Default fetch for @OneToMany? — LAZY — the collection is loaded only when first accessed.
LazyInitializationException cause? — Accessing a lazy proxy after the Hibernate session/persistence context has closed.
How to fetch a lazy association in one query? — Use JOIN FETCH in JPQL or an @EntityGraph.
N+1 problem? — One query for parents plus one extra query per parent to load its association.
Continue Learning
Related Interview Questions
What causes LazyInitializationException, and why is open-session-in-view a poor way to avoid it?
hard
How do you choose between JOIN FETCH, entity graphs and batch fetching when tuning Hibernate reads?
hard
What is Spring Data JPA and how do repository interfaces work?
medium
What is the difference between JpaRepository, CrudRepository, and PagingAndSortingRepository?
medium