Java.Hibernate.Middle.When to use which instrument to solve n+1 problem ?

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 FETCH into your JPQL queries.
  • You’re using JPA 2.1 or newer.

🚨 Avoid if:

  • You need precise control over query shape beyond what EntityGraph allows.

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 IN clauses.

🚨 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 FETCH or EntityGraphs.

🔥 Quick cheatsheet:

ScenarioBest strategy
Need associated data every timeJOIN FETCH
Varying needs for associated dataEntityGraph
Keep lazy loading but reduce N+1 overheadBatch fetching
Loading a page of parents + their childrenSubselect fetching
One-to-one/small always-needed dataEAGER fetching
Special or complex needsManual queries
This entry was posted in Без рубрики. Bookmark the permalink.