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.