DEV Community

Tommy
Tommy

Posted on Edited on

Spring JPA - @EntityGraph

By default, Spring Data JPA loads related data lazily, which can cause the N+1 problem — one query for the main data and more for each related item. @EntityGraph annotation fixes this by letting you load related data in a single query, without changing your entity mapping. It’s simple, improves performance, and avoids writing custom JOIN FETCH queries.

Example

Let’s say you have a Post entity that references an Author.

Entities

@Entity
public class Post {
    @Id
    private Long id;
    private String title;

    @ManyToOne(fetch = FetchType.LAZY)
    private Author author;
}

@Entity
public class Author {
    @Id
    private Long id;
    private String name;
}
Enter fullscreen mode Exit fullscreen mode

Repository

public interface PostRepository extends JpaRepository<Post, Long> {

    // attributePaths specifies related entities to eagerly load
    @EntityGraph(attributePaths = {"author"})
    List<Post> findAll();
}
Enter fullscreen mode Exit fullscreen mode

Now, if you create a simple controller to return all posts and have SQL logging enabled, you'll see the queries printed in the console.

With @EntityGraph, only one query runs to fetch both the post and its author. Without it, multiple queries are executed — one for the posts and one for each author — which is the N+1 problem.

✅ Using @EntityGraph
Only one query — fast and efficient.

select p.id, p.title, a.id, a.name
from post p
left join author a on p.author_id = a.id
Enter fullscreen mode Exit fullscreen mode

🚨 Not Using @EntityGraph
N+1 queries — slow and wasteful.

select * from post;
select * from author where id = ?;
select * from author where id = ?;
Enter fullscreen mode Exit fullscreen mode

For more details on how to use @EntityGraph with Spring Data JPA, check out the official documentation.

Top comments (3)

Collapse
 
sibasis_padhi profile image
Sibasis Padhi •

Great to know about @EntityGraph. A reference about @EntityGraph would have been great for readers to deep dive into it. Overall, good insights.

Collapse
 
shitij_bhatnagar_b6d1be72 profile image
Shitij Bhatnagar •

Thanks for the article, helpful.

Collapse
 
thesearenotthedroids_your profile image
thesearenotthedroids yourelookingfor •

This article is wrong, since in the code presented the N+1 problem is never actually triggered, and @EntityGraph is actually unnecessary in this case and degrades performance. N+1 problem would only be triggered if AFTER findAll You would iterate on returned results and access the mapped property for each of the managed entities- then this ACCESS triggers the lazy load of specific relation and thus another select for each "row". But If you're just doing findAll with lazy fetching (and that's all happening here)- that would never trigger, You are only making a single select- for which case lazyload is actually optimal and @EntityGraph only messes that up with no real reason...