Hibernate provides different kinds of relationships between entities like OneToMany, ManyToOne, ManyToMany or OneToOne. In the early days of Hibernate the fething strategy of all relationships was “lazy”. This stayed true for a long time and changed when Hibernate started to support JPA, because the JPA specification defines different default fetching strategies.
The default fetching strategy up to Hibernate version 4.3 is:
By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.
Hibernate 4.3 manual, 20.1.1. Working with lazy associations
In contrast to this the JPA specification specifies different default fetching strategies per relationship as you can see in the Java Persistence Specification 2.0.
JPA Spec | Relationship | Default Fetch Strategy |
11.1.25 | ManyToMany | LAZY |
11.1.26 | ManyToOne | EAGER |
11.1.36 | OneToMany | LAZY |
11.1.37 | OneToOne | EAGER |
Since Hibernate version 5.0 it applies the same default fetching strategies as JPA:
The Hibernate recommendation is to statically mark all associations lazy and to use dynamic fetching strategies for eagerness. This is unfortunately at odds with the JPA specification which defines that all one-to-one and many-to-one associations should be eagerly fetched by default. Hibernate, as a JPA provider, honors that default.
Hibernate userguide, 11.2. Applying fetch strategies
Therefore you should keep in mind that using Hibernate’s JPA API means that the default lazy loading strategies can be different. So when you wonder why hibernate loads a lot of entities in one big join, you should take a closer look at the fetch type. Because when you rely on the default value it might not be the default you are thinking of.
More references: