Hibernate ORM: Eager or Lazy Loading? When to Use Each

July 5, 2023
4 minutes to read
Share this post:

Hibernate is a well-established Object-Relational Mapping (ORM) framework that is widely used in Java development. This framework helps developers optimize the code for database operations such as fetching data. Choosing the right fetching strategy - Eager Loading or Lazy Loading - is crucial for your application’s performance. In this article, we will examine these two strategies and discuss when and how you should use them in your Spring Data project.

Eager Loading

Eager Loading is a technique where all related data are immediately initialized and fetched when an entity is loaded. It is useful when you expect the related data to be needed in the near future.

public class User {

    @OneToOne(fetch = FetchType.EAGER)
    private Profile profile;

In this example, the Profile object is immediately loaded as soon as a User object is fetched.

Advantages of Eager Loading

  • Preliminary Loading: Eager Loading ensures that all necessary data are already available when the entity is loaded. This can be useful to minimize the number of database queries and possibly improve performance.

  • Simplicity: It requires less consideration for code design as everything is loaded immediately.

Disadvantages of Eager Loading

  • Redundant Data: There is a risk of loading unnecessary data that may not be needed, which can lead to performance issues.

  • Higher Memory Requirement: Since all related data are loaded at once, more memory is needed, which can cause problems with large data sets.

Lazy Loading

Lazy Loading is the opposite of Eager Loading. Here, related data are only loaded when they are actually needed. Hibernate achieves this through the use of proxy objects.

public class User {

    @OneToOne(fetch = FetchType.LAZY)
    private Profile profile;

In this example, the Profile object is only loaded when it is actually used, which delays the initialization.

Advantages of Lazy Loading

  • Efficiency: Since only necessary data are loaded, memory and CPU resources can be used more efficiently.

  • Faster Initialization: The main object can be loaded faster as not all related data have to be loaded immediately.

Disadvantages of Lazy Loading

  • More Database Queries: Since related data are only loaded when needed, this can lead to a larger number of database queries, which can affect performance.

  • Hibernate-Specific Exceptions: If you access a not yet initialized collection or a not yet initialized object outside of a Hibernate session, this can lead to a LazyInitializationException. By introducing a transaction, a Hibernate session implicitly exists. This is usually the desired behavior.

Custom Queries with @Query

Another way to load data is to use custom queries with the @Query annotation. This gives you finer control over the database queries and allows you to make specific optimizations.

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("SELECT u FROM User u JOIN FETCH u.profile WHERE u.id = :id")
    User findByIdAndFetchProfileEagerly(@Param("id") Long id);

In this example, a custom query is used to load the User object and its associated Profile object in a single database query.

Recommendations from Hibernate

According to the official Hibernate documentation, Lazy Loading is the preferred choice as it optimizes performance by loading only the necessary data. Instead of defining the FetchType.EAGER statically in other cases, it is recommended to fall back on dynamic mechanisms like the @Query annotation, an EntityGraph, or the Criteria API.

Nevertheless, the choice of fetching strategy strongly depends on the specific use case and the requirements of the application. It is important to monitor and optimize the application during development and after going live to ensure optimal performance.

Choosing the right data fetching strategy in Hibernate can be challenging but has a significant impact on the performance and efficiency of your application. Both Eager Loading and Lazy Loading have their advantages and disadvantages, and it’s important to consider the context of your application to make the best decision. With custom queries via @Query, you can gain even more control over data fetching.

Have you heard of Marcus' Backend Newsletter?

New ideas. Every week!