✅ Use JOIN FETCH when:
- You always need the associated data in that query’s result (e.g., displaying authors and their books in a UI table).
- You’re only fetching one collection or single-valued associations → avoids Cartesian explosion.
- You want maximum performance with one query.
🚨 Avoid if:
- You need to join multiple collections → can produce huge result sets with duplicated parent rows.
✅ Use EntityGraph when:
- You want to control fetching dynamically at runtime (e.g., REST APIs where some endpoints need extra data, others don’t).
- You prefer not to hardcode
JOIN FETCHinto your JPQL queries. - You’re using JPA 2.1 or newer.
🚨 Avoid if:
- You need precise control over query shape beyond what
EntityGraphallows.
✅ Use Batch fetching (@BatchSize) when:
- You want to keep lazy loading but reduce N+1 overhead.
- You load a list of parents (e.g., orders) and then later access child associations (e.g., order items).
- Your use case includes paging or processing batches of entities.
🚨 Avoid if:
- Your data access pattern doesn’t touch multiple proxies together → batching can’t kick in.
✅ Use Subselect fetching when:
- You load a list of parent entities in one query, and later need their collections.
- You want to avoid both N+1 and Cartesian product issues with
JOIN FETCH. - Your expected parent list size is moderate (tens to low hundreds) → avoids massive
INclauses.
🚨 Avoid if:
- Your parent list can be huge → subselect’s
IN (...)clause could become inefficient or exceed database limits.
✅ Use EAGER fetching when:
- The association is always needed, for example, small one-to-one relationships like
User.profile. - You control entity usage tightly and know loading the association by default is safe.
🚨 Avoid if:
- The association is a collection or large data → eager fetching can load too much data or cause performance bottlenecks.
✅ Use manual queries with WHERE IN (...) when:
- You want precise, explicit control over fetching behavior in your service layer.
- You have a complex access pattern not easily expressed with
JOIN FETCHor EntityGraphs.
🔥 Quick cheatsheet:
| Scenario | Best strategy |
|---|---|
| Need associated data every time | JOIN FETCH |
| Varying needs for associated data | EntityGraph |
| Keep lazy loading but reduce N+1 overhead | Batch fetching |
| Loading a page of parents + their children | Subselect fetching |
| One-to-one/small always-needed data | EAGER fetching |
| Special or complex needs | Manual queries |