N+1 Problem in JPA — Cause and Fix with JOIN FETCH
Fast recall
Quick revision
Core answer
Whether you can identify, explain, and fix the most commonly asked JPA performance bug, and prove it with SQL logging
Fixing N+1 by switching the association to EAGER globally — it just trades one performance problem for another and over-fetches on every query
Show a concrete JOIN FETCH solution and mention @BatchSize as an alternative when JOIN FETCH isn't possible (e.g. pagination), and that you'd confirm with show-sql
Interview-ready guide
Interview answer
If one order query is followed by a customer query for each order, fifty orders can cause fifty-one statements. A JPQL JOIN FETCH for customer or an entity graph can commonly load that bounded to-one graph without per-order selects. For items, a DTO projection or one WHERE order_id IN (...) query may be more suitable. @BatchSize can group unresolved keys, but size 10 does not promise exactly N/10 queries because already-loaded values and final batches vary.
For example, one query returns 100 orders and iteration triggers one customer query per order: that is the N+1 shape. I confirm it with SQL/query metrics and choose a fetch join or projection for that use case rather than marking every relationship eager.
N+1 Problem in JPA — Cause and Fix with JOIN FETCH
Direct Answer
N+1 means one query retrieves N roots and later work issues up to N additional queries for related data. Lazy access in a loop is a common trigger, but eager mappings can also result in secondary selects. Fix the access pattern with a query-specific fetch join, entity graph, DTO projection, one bulk association query, or batch fetching, then verify the SQL. There is no guaranteed one-query fix for every graph.
Common Mistakes & Pitfalls
- Switching to FetchType.EAGER globally — fixes this case but loads the association on every query, with no per-query opt-out.
- Not enabling query logging — you can't see N+1 without SQL logs; turn on
spring.jpa.show-sql=trueandhibernate.format_sql=true. - JOIN FETCH with pagination — combining JOIN FETCH and
Pageablemakes Hibernate load all rows and paginate in memory; use @EntityGraph or @BatchSize for paginated queries with associations.
Check your understanding
Answer these without looking back at the article.
- How do you use @EntityGraph in Spring Data JPA?
- What is @BatchSize in Hibernate and how does it reduce N+1?
- How do you detect N+1 problems in a Spring Boot application?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.