Davide
Davide

Reputation: 508

JPA Annotation ElementCollection eager fetching in Spring boot

I have a small problem with fetching eagerly in spring boot. Basically, I have an entity defined as:

@Entity
class EventEntry(
        @ID
        val uid 

        @ElementCollection(fetch = FetchType.EAGER)
        @CollectionTable(name = "event_to_boxes", joinColumns = arrayOf(JoinColumn(name = "event_uid")))
        @Column(name = "box_uid")
        val boxUids: List<Long>
) : EventEntry(userUid, timestamp)

Now, when I am inserting data (from graphql but it's a detail), everything works fine, and I can see that on the database multiple rows are correctly persisted on the event_to_boxes table. Unfortunately, when I am retrieving all the events, something unexpected pops up.

What I see is the query asking for all the events, THEN asking once for every single list of boxUids, almost as if the FetchType.EAGER was completely ignored.

My understanding was that fetch type eager should have already got the values for the box uids when populating the event entitities. Did I miss anything or is my understanding completely wrong?

To Give a little bit more of background, I am trying to model a N-to-N relationship this way, where this is one half of the N-relationship, but I must, when getting the event entity also bring up the box uids (box is the other half of the relationship) without any additional box data

Upvotes: 0

Views: 2119

Answers (1)

SternK
SternK

Reputation: 13041

As explained in the hibernate documentation, the FetchType.EAGER will work only for a direct entity fetching:

EventEntry eventEntry = entityManager.find(EventEntry.class, 1L);

The LEFT JOIN clause is added to the generated SQL query because this association is required to be fetched eagerly.

On the other hand, if you are using an entity query that does not contain a JOIN FETCH directive ...

Hibernate uses a secondary select instead. This is because the entity query fetch policy cannot be overridden, so Hibernate requires a secondary select to ensure that the EAGER association is fetched prior to returning the result to the user.

If you forget to JOIN FETCH all EAGER associations, Hibernate is going to issue a secondary select for each and every one of those which, in turn, can lead to N+1 query issues.

For this reason, you should prefer LAZY associations.

Upvotes: 3

Related Questions