1. Introduction

When working with an ORM, data fetching/loading can be classified into two types: eager and lazy.

In this quick article we are going to point out differences and show those can be used in Hibernate.

2. Maven Dependencies

In order to use Hibernate, let's first define the main dependencyin our pom.xml:


The latest version of Hibernate can be found here.

3. Eager and Lazy Loading

The first thing that we should discuss here is what lazy loading and eager loading are:

  • Eager Loading is a design pattern in which data initialization occurs on the spot
  • Lazy Loading is a design pattern which is used to defer initialization of an object as long as it's possible

Let's see how this actually works with some examples:

The UserLazy class:

@Table(name = "USER")
public class UserLazy implements Serializable {

    @Column(name = "USER_ID")
    private Long userId;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
    private Set<OrderDetail> orderDetail = new HashSet();

    // standard setters and getters
    // also override equals and hashcode


The OrderDetail class:

@Table (name = "USER_ORDER")
public class OrderDetail implements Serializable {
    private Long orderId;
    @ManyToOne(fetch = FetchType.LAZY)
    private UserLazy user;

    // standard setters and getters
    // also override equals and hashcode


One User can have multiple OrderDetails. In eager loading strategy, if we load the User data, it will also load up all orders associated with it and will store it in a memory.

But, when lazy loading is enabled, if we pull up a UserLazy, OrderDetail data won't be initialized and loaded into a memory until an explicit call is made to it.

In the next section we will see how the above example is implemented in Hibernate.

4. Loading Configuration

In this section we will look at how can we configure fetching strategies in Hibernate. We will reuse examples from the previous section.

Lazy Loading can be simply enabled using the following annotation parameter:

fetch = FetchType.LAZY

To use Eager Fetching the following parameter is used:

fetch = FetchType.EAGER

To setup Eager Loading we have used UserLazy‘s twin class called UserEager.

In the next section we will look at the differences between the two types of fetching.

5. Differences

As we mentioned, the main difference between the two types of fetching is a moment when data gets loaded into a memory.

Let's have a look at this example:

List<UserLazy> users = sessionLazy.createQuery("From UserLazy").list();
UserLazy userLazyLoaded = users.get(3);
return (userLazyLoaded.getOrderDetail());

With the lazy initialization approach, orderDetailSet will get initialized only when it is explicitly called by using a getter or some other method as shown in the above example:

UserLazy userLazyLoaded = users.get(3);

But with an eager approach in UserEager it will be initialized immediately in the first line of above example:

List<UserEager> user = sessionEager.createQuery("From UserEager").list();

For lazy loading a proxy object is used and a separate SQL query is fired to load the orderDetailSet .

The idea of disabling proxies or lazy loading is considered a bad practice in Hibernate. It can result in a lot of data being fetched from a database and stored in a memory, irrespective of the need for it.

The following method can be used to test the above functionality:


Now it is important to have a look at the queries that are generated in either case:

<property name="show_sql">true</property>

The above setting in the fetching.hbm.xml shows the SQL queries that are generated. If you look at a console output then you will be able to see generated queries.

For Lazy Loading the query that is generated to load the User data:

select user0_.USER_ID as USER_ID1_0_,  ... from USER user0_

However, in eager loading, we saw a join being made with USER_ORDER:

select orderdetai0_.USER_ID as USER_ID4_0_0_, orderdetai0_.ORDER_ID as ORDER_ID1_1_0_, orderdetai0_ ...
  from USER_ORDER orderdetai0_ where orderdetai0_.USER_ID=?

The above query is generated for all Users, which results in much more memory being used than in the other approach.

6. Advantages and Disadvantages

6.1. Lazy Loading


  • Initial load time much smaller than in the other approach
  • Less memory consumption than in the other approach


  • Delayed initialization might impact performance during unwanted moments
  • In some cases you need to handle lazily-initialized objects with a special care or you might end up with an exception

6.2. Eager Loading:


  • No delayed initialization related performance impacts


  • Long initial loading time
  • Loading too much unnecessary data might impact performance

7. Lazy Loading in Hibernate

Hibernate applies lazy loading approach on entities and associations by providing a proxy implementation of classes.

Hibernate intercepts calls to an entity by substituting it with a proxy derived from an entity’s class. In our example, when a requested information is missing, it will be loaded from a database before control is ceded to the User class implementation.

It should also be noted that when the association is represented as a collection class (in the above examples it is represented as Set<OrderDetail> orderDetailSet), then a wrapper is created and substituted for an original collection.

To know more about proxy design pattern you can refer here.

8. Conclusion

In this article, we showed examples of the two main types of fetching that are used in Hibernate.

For advanced level expertise, you can look at the official website of Hibernate. To get the code discussed in this article please have a look at this repository.