Solving N+1 with @EntityGraph
Fast recall
Quick revision
Core answer
@EntityGraph(attributePaths = {"customer", "items"}) and Hibernate generates a LEFT JOIN FETCH for those attributes only for that query, leaving the entity's default FetchType.LAZY intact for every other query. It is cleaner than writing JPQL JOIN FETCH by hand, composes with derived queries (no @Query needed), and accepts both ad-hoc attributePaths and reusable `@NamedEntityGraph` declarations on the entity. The two graph types — `FETCH` (only graph attributes are eager, all others LAZY) and `LOAD` (graph attributes eager, others follow entity defaults) — let you override EAGER-mapped associations back to LAZY per query. Same pagination caveat as JOIN FETCH: collection graphs + Pageable trigger in-memory pagination (HHH90003004). For paginated list views, use `@BatchSize`.Practical knowledge of Spring Data JPA features beyond `findAll()` — whether the candidate knows declarative fetch strategies
Using `JOIN FETCH` in a paginated query, which causes Hibernate to load everything in memory and apply pagination in Java — `@EntityGraph` triggers a similar issue, so handle pagination carefully
Explain the difference between FETCH and LOAD graph types, and demonstrate `@NamedEntityGraph` on the entity class for reuse
Interview-ready guide
Interview answer
@EntityGraph solves N+1 by telling Hibernate which associations to fetch eagerly for a specific query, without changing the entity's default fetch strategy. It is the clean solution when JOIN FETCH breaks pagination.
How it works:
- Declare an ad-hoc graph on the repository method:
@EntityGraph(attributePaths = {"items", "items.product"}) - Hibernate translates this to LEFT JOIN FETCH on those paths for that query only
- The entity's
@OneToMany(fetch = LAZY)stays LAZY for all other queries
Named vs ad-hoc graphs:
- Named:
@NamedEntityGraph(name = "Order.withItems", attributeNodes = @NamedAttributeNode("items"))on the entity class; reference by name - Ad-hoc:
@EntityGraph(attributePaths = {"items"})directly on the repository method — preferred for most cases
Pagination compatibility:
JOIN FETCH+Pageableon a collection triggers HHH90003004 warning and in-memory pagination — dangerous on large datasets@EntityGraphcarries the same caveat — for paginated collections, paginate IDs first or use@BatchSize
Over-fetching trap:
- Fetching multiple
@OneToManyassociations in one graph produces a Cartesian product - Prefer separate queries or DTO projections when you need data from multiple collection associations
Solving N+1 with @EntityGraph
Direct Answer
@EntityGraph is Spring Data's declarative answer to N+1: annotate a repository method with @EntityGraph(attributePaths = {"customer", "items"}) and Hibernate generates a LEFT JOIN FETCH for those attributes only for that query, leaving the entity's default FetchType.LAZY intact for every other query. It is cleaner than writing JPQL JOIN FETCH by hand, composes with derived queries (no @Query needed), and accepts both ad-hoc attributePaths and reusable @NamedEntityGraph declarations on the entity. The two graph types — FETCH (only graph attributes are eager, all others LAZY) and LOAD (graph attributes eager, others follow entity defaults) — let you override EAGER-mapped associations back to LAZY per query. Same pagination caveat as JOIN FETCH: collection graphs + Pageable trigger in-memory pagination (HHH90003004). For paginated list views, use @BatchSize.
Common Mistakes & Pitfalls
Using JOIN FETCH in a paginated query, which causes Hibernate to load everything in memory and apply pagination in Java — @EntityGraph triggers a similar issue, so handle pagination carefully
Check your understanding
Answer these without looking back at the article.
- What is the difference between `EntityGraph.EntityGraphType.FETCH` and `LOAD`?
- How would you handle pagination when you need to eagerly load a `@OneToMany` collection?
- Can you combine `@EntityGraph` with a custom `@Query` JPQL method?
- How do `@NamedSubgraph` declarations let you build deep graphs?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.