Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

NPI – JPA Buddy – JPA (partner)
announcement - icon

JPA is huge! It covers nearly every aspect of communication between relational databases and the Java application and is deeply integrated into all major frameworks.

If you're using IntelliJ, JPA Buddy is super helpful. The plugin gently guides you through the subtleties of the most popular JPA implementations, visually reminds you of JPA features, generates code that follows best practices, and integrates intelligent inspections to improve your existing persistence code.

More concretely, it provides powerful tooling to generate Spring Data JPA repositories and methods, Flyway Versioned Migrations, Liquibase Differential Changelogs, DDL and SQL statements, DTO objects, and MapStruct interfaces.

Oh, and it actually generates JPA entities from an existing database and gradually update the data model as the database evolves! Yeah.

>> Become a lot more productive with JPA Buddy

1. Overview

Simply put, Entity Graphs are another way to describe a query in JPA 2.1. We can use them to formulate better-performing queries.

In this tutorial, we're going to learn how to implement Entity Graphs with Spring Data JPA through a simple example.

2. The Entities

First, let's create a model called Item which has multiple characteristics:

public class Item {

    private Long id;
    private String name;
    @OneToMany(mappedBy = "item")
    private List<Characteristic> characteristics = new ArrayList<>();

    // getters and setters

Now let's define the Characteristic entity:

public class Characteristic {

    private Long id;
    private String type;
    @ManyToOne(fetch = FetchType.LAZY)
    private Item item;

    //Getters and Setters

As we can see in the code, both the characteristics field in the Item entity and the item field in the Characteristic entity are loaded lazily using the fetch parameter. So, our goal here is to load them eagerly at runtime.

3. The Entity Graphs

In Spring Data JPA, we can define an entity graph using a combination of @NamedEntityGraph and @EntityGraph annotations. Or, we can also define ad-hoc entity graphs with just the attributePaths argument of the @EntityGraph annotation.

Let's see how it can be done.

3.1. With @NamedEntityGraph

First, we can use JPA's @NamedEntityGraph annotation directly on our Item entity:

@NamedEntityGraph(name = "Item.characteristics",
    attributeNodes = @NamedAttributeNode("characteristics")
public class Item {

And then, we can attach the @EntityGraph annotation to one of our repository methods:

public interface ItemRepository extends JpaRepository<Item, Long> {

    @EntityGraph(value = "Item.characteristics")
    Item findByName(String name);

As the code shows, we've passed the name of the entity graph, which we've created earlier on the Item entity, to the @EntityGraph annotation. When we call the method, that's the query Spring Data will use.

The default value of the type argument of the @EntityGraph annotation is EntityGraphType.FETCH. When we use this, the Spring Data module will apply the FetchType.EAGER strategy on the specified attribute nodes. And for others, the FetchType.LAZY strategy will be applied.

So in our case, the characteristics property will be loaded eagerly, even though the default fetch strategy of the @OneToMany annotation is lazy.

One catch here is that if the defined fetch strategy is EAGER, then we cannot change its behavior to LAZY. This is by design since the subsequent operations may need the eagerly fetched data at a later point during the execution.

3.2. Without @NamedEntityGraph

Or, we can define an ad-hoc entity graph, too, with attributePaths.

Let's add an ad-hoc entity graph to our CharacteristicsRepository that eagerly loads its Item parent:

public interface CharacteristicsRepository 
  extends JpaRepository<Characteristic, Long> {
    @EntityGraph(attributePaths = {"item"})
    Characteristic findByType(String type);    

This will load the item property of the Characteristic entity eagerly, even though our entity declares a lazy-loading strategy for this property.

This is handy since we can define the entity graph inline instead of referring to an existing named entity graph.

4. Test Case

Now that we've defined our entity graphs let's create a test case to verify it:

@Sql(scripts = "/entitygraph-data.sql")
public class EntityGraphIntegrationTest {
    private ItemRepository itemRepo;
    private CharacteristicsRepository characteristicsRepo;
    public void givenEntityGraph_whenCalled_shouldRetrunDefinedFields() {
        Item item = itemRepo.findByName("Table");
    public void givenAdhocEntityGraph_whenCalled_shouldRetrunDefinedFields() {
        Characteristic characteristic = characteristicsRepo.findByType("Rigid");

The first test will use the entity graph defined using the @NamedEntityGraph annotation.

Let's see the SQL generated by Hibernate:

    item0_.id as id1_10_0_,
    characteri1_.id as id1_4_1_,
    item0_.name as name2_10_0_,
    characteri1_.item_id as item_id3_4_1_,
    characteri1_.type as type2_4_1_,
    characteri1_.item_id as item_id3_4_0__,
    characteri1_.id as id1_4_0__
    item item0_ 
left outer join 
    characteristic characteri1_ 

For comparison, let's remove the @EntityGraph annotation from the repository and inspect the query:

    item0_.id as id1_10_,
    item0_.name as name2_10_ 
    item item0_ 

From these queries, we can clearly observe that the query generated without @EntityGraph annotation is not loading any properties of Characteristic entity. As a result, it loads only the Item entity.

Lastly, let's compare the Hibernate queries of the second test with the @EntityGraph annotation:

    characteri0_.id as id1_4_0_,
    item1_.id as id1_10_1_,
    characteri0_.item_id as item_id3_4_0_,
    characteri0_.type as type2_4_0_,
    item1_.name as name2_10_1_ 
    characteristic characteri0_ 
left outer join 
    item item1_ 

And the query without the @EntityGraph annotation:

    characteri0_.id as id1_4_,
    characteri0_.item_id as item_id3_4_,
    characteri0_.type as type2_4_ 
    characteristic characteri0_ 

5. Conclusion

In this tutorial, we've learned how to use JPA Entity Graphs in Spring Data. With Spring Data, we can create multiple repository methods that are linked to different entity graphs.

The examples for this article are available over on GitHub.

Persistence bottom

Get started with Spring Data JPA through the reference Learn Spring Data JPA course:

Persistence footer banner
Comments are closed on this article!