Spring Data Hibernate: How to use fetch type specified in entity for custom queries?

483 Views Asked by At

I'm working on a Spring Boot 3.x application with Spring Data and Hibernate 6.x. I've got an entity class that looks like this:

@Entity
public class User {

    @Id
    private UUID id = UUID.randomUUID();

    @Column
    private String country;

    @ManyToMany(fetchType = FetchType.EAGER)
    private Set<Role> roles;

    // constructors, getters, setters, equals/hashcode based on id
}

When I do a custom query like this in a repository:

@Query("""
   FROM User user
   WHERE user.country = ?1
""")
public Set<User> getUserByCountry(String country);

... I get back a Set<User>, but their roles property is lazily loaded by Hibernate; I can clearly see that from the SQL query logging. One query for roles is sent to the DB for each user.

Now, I've been around for a while, and I clearly remember that FetchType.EAGER was frowned upon because it affected all queries and you could not opt-out of it. However, this clearly contradicts this case; lazy fetching is performed even if the roles reference is marked as EAGER. Did that behavior change in recent (major) versions of Hibernate? Can I tell Hibernate to always fetch the eager associations by default for all custom queries?

I tried using @EntityGraph to explicitly tell the custom query to fetch the roles reference eagerly. That works nicely, but I would strongly prefer hibernate to infer this information from the annotations on the entities if no @EntityGraph annotation is provided.

EDIT: I verified yesterday that the fetch behavior was in fact different with spring boot 2.x and hibernate 5.x. This appears to be a Hibernate 6.x thing.

1

There are 1 best solutions below

0
Christian Beikov On

The generated SQL query should include a join to fetch the roles as part of your main query. It could be, that in your real model, when you have multiple of such eager collections, that Hibernate has to issue separate queries to avoid multiple bag fetches, which would alter the cardinality of the result. If you just have a single eager collection though, please create an issue in the issue tracker(https://hibernate.atlassian.net) with a test case(https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-6/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java) that reproduces the issue.