Jpa OneToOne N+1 Issue#
Fix N+1 Issue With OneToOne Relationship in Jpa.#
- In Jpa if we define
OneToOne
relationship as below.
CustomerEntity.java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
|
LoyaltyCardEntity.java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
- Then when we query to get a
CustomerEntitty
, we will see in the log that every time we get aLoyaltyCardEntity
, a hibernate query will be generated base on how manyLoyaltyCard
in the list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
-
So how do you think if there are 10000 customers with 10000 loyaltycards. This will make the database execute thousands queries and it will lead to bad performance.
-
To avoid it, we will use the
Entity Graphs
which are a feature introduced in JPA 2.1 that provides a more sophisticated method of dealing with performance loading. They provide a way to define which attributes (fields) of an entity should be loaded from the database when the entity is fetched. This can be particularly useful when dealing with entities that have relationships with other entities. -
The main goal of the JPA
Entity Graph
is to improve the runtime performance when loading the entity’s related associations and basic fields1. The JPA provider loads all the graphs in one select query and then avoids fetching associations with moreSELECT
queries. This is considered a good approach for improving application performance. -
In Spring Boot, we can define an
Entity Graph
using a combination of@NamedEntityGraph
and@EntityGraph
annotations. We can also define ad-hoc entity graphs with just theattributePaths
argument of the@EntityGraph
annotation.
With @NamedEntityGraph#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
- Then in the
repository
we just define thefindAll
method with@EntityGraph
annotation.
CustomerRepository.java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Without @NamedEntityGraph#
- Then in the
repository
we just define thefindAll
method with@EntityGraph
annotation usingattributePaths
.
CustomerRepository.java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
-
With this approach, we don't need to use
@NamedEntityGraph
annotation in theCustomerEntity
. -
References: