Spring Boot JPA Batch Fetching: Optimize Large Queries & Fix N+1 Problem
When working with Spring Data JPA, performance is one of the most critical aspects of handling large datasets efficiently. A common issue developers face is the N+1 query problem, where Hibernate executes too many queries when fetching related entities.
To solve this, we use Batch Fetching to optimize database queries and improve application speed. This guide covers everything from scratch, step by step, with real code examples and a REST API to test each case.
1. What is Batch Fetching and Why It Matters?
The N+1 Query Problem
Imagine we have a Department
entity, each with multiple Employee
records. When you fetch a list of departments, Hibernate loads them first. But when you access department.getEmployees()
, Hibernate fires one query per department to fetch employees.
If you have 10 departments, this results in 1 + 10 = 11 queries, which is inefficient and can slow down performance.
Example of the Problem:
Generated SQL:
💥 More queries = More database load = Slow performance.
2. Setting Up a Spring Boot Project
Required Dependencies
Add the following dependencies in pom.xml
:
Database Configuration (H2 In-Memory)
3. Defining Entities
Department Entity
Employee Entity
4. Fixing the N+1 Problem with Batch Fetching
To enable batch fetching in Hibernate, we can configure it in application.properties
:
🔹 Now, instead of multiple queries, Hibernate fetches employees in batches of 10.
Generated SQL:
🔥 Fewer queries = Faster performance.
5. Alternative: Using @BatchSize
Annotation
Instead of configuring batch size globally, we can do it at the entity level:
6. Optimizing Further with JOIN FETCH
Another way to solve the N+1 problem is to fetch related entities in one query using JOIN FETCH
.
Modify the repository like this:
Generated SQL:
✔ One query, all data loaded efficiently.
7. Adding a REST API for Testing
To test all scenarios, let's expose REST endpoints:
Testing Endpoints
1️⃣ Normal Fetching (N+1 Problem)
2️⃣ Optimized with Batch Fetching
3️⃣ Optimized with JOIN FETCH
8. Conclusion
Use batch fetching for large datasets. Use JOIN FETCH
for immediate needs.