DEV Community

Shubham Bhati
Shubham Bhati

Posted on

Solving the Hibernate N+1 Problem in Spring Data JPA

Hibernate N+1 Problem

Published 2026-05-25 by Shubham Bhati — Backend Engineer (Java 17, Spring Boot, Microservices).

We've all been there - staring at a slow application, trying to figure out why our database queries are taking so long to execute. In our case, it was a Java-based e-commerce platform built using Spring Boot 3.2 and Spring Data JPA. After digging through the logs, we discovered that the hibernate n+1 problem was the culprit behind the slow performance. This issue occurs when Hibernate executes multiple select queries to fetch related entities, resulting in a significant increase in database load and latency. In this article, we'll explore the causes of the hibernate n+1 problem and discuss various strategies to solve it.

Introduction to the Hibernate N+1 Problem

The hibernate n+1 problem is a common issue that arises when using Hibernate to fetch related entities. It occurs when Hibernate executes multiple select queries to fetch the related entities, instead of using a single query to fetch all the required data. For example, consider a simple Order entity that has a one-to-many relationship with OrderItem:

@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String customerName;
    @OneToMany(mappedBy = "order")
    private List<OrderItem> orderItems;
    // getters and setters
}
Enter fullscreen mode Exit fullscreen mode

When we try to fetch all the orders along with their order items, Hibernate will execute a separate query to fetch the order items for each order, resulting in the n+1 problem.

Understanding JPA Fetch Types

JPA provides two fetch types - EAGER and LAZY. The EAGER fetch type fetches the related entities immediately when the parent entity is loaded, while the LAZY fetch type fetches the related entities only when they are actually needed. By default, Hibernate uses the LAZY fetch type for one-to-many and many-to-many relationships. However, this can lead to the n+1 problem if we're not careful. We can change the fetch type to EAGER using the fetch attribute:

@OneToMany(mappedBy = "order", fetch = FetchType.EAGER)
private List<OrderItem> orderItems;
Enter fullscreen mode Exit fullscreen mode

However, this can lead to performance issues if we're dealing with large amounts of data.

Lazy Loading and Its Pitfalls

Lazy loading can be a powerful tool for improving performance, but it can also lead to the n+1 problem if we're not careful. Consider the following example:

Order order = entityManager.find(Order.class, 1L);
for (OrderItem orderItem : order.getOrderItems()) {
    System.out.println(orderItem.getName());
}
Enter fullscreen mode Exit fullscreen mode

In this example, Hibernate will execute a separate query to fetch the order items for each order, resulting in the n+1 problem. To avoid this, we can use join fetching or batch fetching.

Using Join Fetching to Solve the N+1 Problem

Join fetching involves using a single query to fetch all the required data. We can use the JOIN FETCH keyword in our JPQL query to achieve this:

Query<Order> query = entityManager.createQuery("SELECT o FROM Order o JOIN FETCH o.orderItems WHERE o.id = :id", Order.class);
query.setParameter("id", 1L);
Order order = query.getSingleResult();
Enter fullscreen mode Exit fullscreen mode

This will fetch the order along with its order items in a single query, avoiding the n+1 problem.

Enabling Batch Fetching

Batch fetching involves fetching multiple related entities in a single query. We can enable batch fetching using the @BatchSize annotation:

@OneToMany(mappedBy = "order")
@BatchSize(size = 10)
private List<OrderItem> orderItems;
Enter fullscreen mode Exit fullscreen mode

This will fetch the order items in batches of 10, reducing the number of queries executed.

Common Mistakes

Here are some common mistakes to avoid when dealing with the hibernate n+1 problem:

  • Not using join fetching or batch fetching
  • Using the LAZY fetch type without considering the performance implications
  • Not using the @BatchSize annotation to enable batch fetching
  • Not using the JOIN FETCH keyword in JPQL queries
  • Not optimizing database queries to reduce latency

FAQ

What is the hibernate n+1 problem?

The hibernate n+1 problem is a common issue that arises when using Hibernate to fetch related entities. It occurs when Hibernate executes multiple select queries to fetch the related entities, instead of using a single query to fetch all the required data.

How can I solve the hibernate n+1 problem?

You can solve the hibernate n+1 problem by using join fetching or batch fetching. Join fetching involves using a single query to fetch all the required data, while batch fetching involves fetching multiple related entities in a single query.

What is the difference between EAGER and LAZY fetch types?

The EAGER fetch type fetches the related entities immediately when the parent entity is loaded, while the LAZY fetch type fetches the related entities only when they are actually needed.

How can I optimize database queries to reduce latency?

You can optimize database queries by using indexes, reducing the amount of data fetched, and using efficient query algorithms. For more information, you can refer to the Oracle documentation or the Spring documentation.

Conclusion

In conclusion, the hibernate n+1 problem is a common issue that can significantly impact the performance of your application. By using join fetching or batch fetching, you can avoid this problem and improve the performance of your database queries. For more information, you can refer to the Baeldung tutorial or the official Java tutorials. Remember to always consider the trade-offs between different approaches and optimize your database queries to reduce latency.


Hibernate N+1 Problem in production

Further Reading


Written by **Shubham Bhati* — Backend Engineer at AlignBits LLC, specializing in Java 17, Spring Boot, microservices, and AI integration. Connect on LinkedIn, GitHub, or read more at shubh2-0.github.io.*

Top comments (0)