≑ Menu

Hibernate Eager vs Lazy Fetch Type


The topic of Fetch types in Hibernate is a fairly advanced topic, as it requires you to have a decent understanding of the Java programming language, as well as have had exposure to SQL and the Hibernate framework for Java. In this post I’m going to assume that you posses this knowledge, if you do not, then I suggest you follow along with my podcasts available here.

What the heck is a Fetch Type?

Great question! Hibernate is a very handy framework for removing your need to fully understand SQL, but it will force you to understand things such as joins.

Joining two tables in SQL is the foundation of a relational database, as joins allow you to actually define relationships between tables (objects).

Having said that, relationships are important to understand when talking about fetch types in Hibernate. This is the case because whenever you define a relationship in Hibernate, you’ll also need to define the fetch type. The fetch type essentially decides whether or not to load all of the relationships of a particular object/table as soon as the object/table is initially fetched.

An example of this would be as follows, consider this User object:

public class User
  import javax.persistence.OneToOne;
  import javax.persistence.JoinColumn;

  private String username;
  private String password;
  private Profile userProfile;

  // omitting code for getters and setters for username, password

  private Profile getUserProfile()
    return userProfile;

  private void setUserProfile(Profile userProfile)
    this.userProfile = userProfile;

Can you spot the relationship in this User object?

If you can’t, no worries, there’s an easy way to spot it!

Any time you see a @OneToOne, @OneToMany or @ManyToMany annotations, you’ve got a relationship. What’s important to note is that the fetch type should be specified within those annotations, if you don’t specify one then it defaults to FetchType.LAZY.

What this means is that when you load up an instance of the User class via a Hibernate query, Hibernate will NOT load this User’s Profile unless you explicitly ask it to. So this means that if you try to call user.getUserProfile(), you’ll get a NULL.

Difference Between EAGER and LAZY

Okay, so we talked about the fact that FetchType.LAZY is the default fetch type for all Hibernate annotation relationships. We also talked about the fact that when you use the Lazy fetch type, Hibernate won’t load the relationships for that particular object instance. So then, what’s the difference between Eager and Lazy?

Fetch type Eager is essentially the opposite of Lazy, Eager will by default load ALL of the relationships related to a particular object loaded by Hibernate. This means that if you change the relationship to be this:

  import javax.persistence.FetchType;

  private Profile getUserProfile()
    return userProfile;

Hibernate will now load the user profile into the user object by default. This means that if you access user.getUserProfile() it won’t be NULL (unless the joining table actually doesn’t contain a matching row by the “user_profile_id” join column).

So, the long story short here is:

FetchType.LAZY = Doesn’t load the relationships unless explicitly “asked for” via getter
FetchType.EAGER = Loads ALL relationships

Pros and Cons

If using the lazy loading approach can cause NullPointerExceptions, then why the heck would you want to use it? Well, let’s just take a minute to think about this.

Let’s assume we had a User object that has 10 different relationships to other objects. Let’s also say that you have a user that’s trying to login and you just want to check to see if their username and password is correct and matches what’s stored in the database. Would you really want to load ALL 10 relationships and NOT make use of ANY of those loaded relationships? Remember, loading things from a database is fairly “expensive” in terms of the time it takes to load all that information into a Java objects AND keep them in memory. And what happens if one of the relationships points to an object that ALSO has 10 relationships (and all of those are set up as fetch type EAGER). Think of the cascading massacre of objects loaded from the database into memory!

The way I like to put it is like this:

    • EAGER: Convenient, but slow
    • LAZY: More coding, but much more efficient

How to Properly use Lazy Loading w/ Spring

So having outlined the differences between these two approaches, I hope you realize that Lazy loading is a suggested route to take your application code in most scenarios. So having said that, how do we make use of Lazy loading with a Spring enabled application?

The important thing to remember is that when using a Spring/Hibernate application, there’s a bit of code that is handled for you in the background that you don’t actually see. The code that you don’t see is the transactional code (enabled by the @Transactional annotation in your DAOs) and this is something that you always need to keep in mind when using Lazy loading.

Having said that, let’s take a look at an example of Lazy loading using our User object. Let’s assume we have our User object which has a Lazy load fetch enabled to the Profile object. So we will need to design our UserDao with this relationship in mind. One approach is to create two separate getter methods like so:

* This UserDao object is being constructed under the assumption that the relationship
*  to the Profile object is being Lazily loaded using FetchType.LAZY
public class UserDao
  private SessionFactory sessionFactory;

  public User getUserById(Long userId)
    Session session = sessionFactory.getCurrentSession();

    // this will invoke the 
    return (User) session.createCriteria(User.class).add(Restrictions.idEq(userId)).uniqueResult();

  public User getUserWithProfileById(Long userId)
    Session session = sessionFactory.getCurrentSession();

    User user = (Users) session.createCriteria(User.class).add(Restrictions.idEq(userId)).uniqueResult();
    // this will force SQL to execute the query that will join with the user's profile and populate
    //  the appropriate information into the user object.

    return user;

In the code above you see that we have created two getter methods to load the User object from our database via Hibernate.

This means that when you want to load a User object without any relationships (i.e. when you’re checking to see if the login information is valid) then you can call getUserById and this will bypass the unnecessary join to the Profile object/table. But if you are in a situation where you DO need to refer to the User‘s profile, then you can call the getUserWithProfileById.

Make sense?

Fun Fact

I was struggling with this Lazy loading concept at first and I’ll share the secret as to why. If you are using lazy loading and you were to invoke the getUserById method, you know that it won’t load the profile relationship… but what happens if you’ve inserted a breakpoint into this getUserById method and you CLICK on the user’s profile listing in the “Variables” tab inside of Eclipse/STS?

Hibernate will automatically invoke that SQL join and populate the relationship for you!

This was confusing the heck out of me because when I clicked on the profile, it was showing up just fine in the “variables” section, and then my subsequent code was working normally (I wasn’t getting NullPointerExceptions) This was so strange and it wasn’t until I looked at the console log that I realized as SOON as I clicked on that profile property, hibernate was executing the SQL query and populating the object.

So be wary, it’s almost like a quantum physics problem… the act of observing lazy loading changes the outcome of the code flow!

Also, be sure to grab the free Video Tutorial for Eager vs Lazy Loading in Hibernate

With those words of wisdom, I wish you happy learning folks πŸ™‚

The Best 7 Java Programming Resources

Alright, so if you’re read this far down the article, then you’re clearly interested in learning how to code. We actually have a free guide that outlines the best 7 resources for Java programmers.

When you sign up you’ll receive the guide immediately and you’ll also receive a few emails a week that will help you speed up your Java learning process so you can get up and running as fast as possible.

Go ahead an click the button below to get started!

CAREFUL! Don’t Push This Button If You’re Not Ready To FINALLY Learn How to Code

{ 60 comments… add one }
  • Kaushik Shrestha November 29, 2013, 7:09 am

    Very good article!! crystal cleared the concept of the 2 fetch types – lazy loading and eager fetch… specially the fact about the breakpoints is an eye-opener.

    • Anonymous August 18, 2015, 10:16 pm

      Good understanding

  • Akbar December 31, 2013, 6:19 am

    Good article…

  • Prem January 15, 2014, 1:34 am

    Nice Article..!!

  • Nitin February 6, 2014, 7:56 am

    Very Nice Article.

  • Tuyen February 17, 2014, 10:45 pm

    Wow! It’s nice. Thank you very much. It helps me alot! ^^!

  • Pally Gharmount February 20, 2014, 5:07 am

    Hi, Very good article, however i could not see the difference between the methods getUserById & getUserWithProfileById that shows the Eager loading. If the domain object is loaded Lazy how would the getUserWithProfileById method get the profile? They both look identical.

    • Trevor Page February 25, 2014, 6:36 am

      Thanks for the comment, I love getting questions!

      The main different is in this key line of code:

      This magical line will force Hibernate to load the joined table into your Users class for later use πŸ™‚

      Hope that helps,


  • pk March 20, 2014, 5:12 pm

    Thanks. Magic line helped me πŸ™‚

  • Siddiqa April 5, 2014, 3:12 am

    Very Good Article ! Thank You Very Much !

  • veeru May 21, 2014, 5:52 am

    very useful

  • zafar pavez June 20, 2014, 5:09 am

    Simply Awesome….

  • Luca July 8, 2014, 6:40 am

    Hi Trevor,
    You wrote that “if you try to call user.getUserProfile() [with lazy fetch], you’ll get a NULL.” This is not true! As soon as you access the userProfile property, Hibernate will execute the query that will retrieve the user’s profile from the user/profile relationship. Lazy fetch doesn’t mean that join queries are not executed. It simply means that join queries are executed when needed – i.e. the first time a property from the related table is accessed.
    You too wrote it in the last section of this article, “Fun Fact”: “Hibernate will automatically invoke that SQL join and populate the relationship for you!” So, you seem to contradict yourself, don’t you?

    • Trevor Page July 9, 2014, 10:56 am

      Hi Luca,

      It’s been a while since I posted this particular tutorial, but if my memory serves, whenever I ran the program it would return NULL for the join. I believe the reason was because it was throwing an exception. Until I debugged it, then it would actually invoke the fetch, which would solve the exception issue.

    • Jamil October 10, 2014, 3:33 am

      I guess Luca is right. In both eager and lazy fetch the value form userProfile gets fetched from database. The difference between them is the ‘UserProfile’ is fetched from database only when user.getUserProfile () is executed, where as in case of eager fetch, the value for ‘UserProfile’ is fetched fully at the time their parent(User) is fetched. The above explanation for lazy fetch is wrong. Other wise its a nice article.

    • Rahul Arora December 12, 2014, 12:01 pm

      Yes, the contradiction is clearly there.

      • Anonymous December 26, 2014, 12:13 pm

        The contradiction only exists if you call user.getUserProfile() in the UserDao class. That’s because this code is being executed inside a Hibernate session. If you tried to call user.getUserProfile() outside of the UserDao (and outside of the Hibernate session) you would then experience the difference between Lazy and Eager loading.

        • Trevor Page January 6, 2015, 2:39 pm

          Exactly. Thanks for answering this question on my behalf πŸ™‚

  • Ruwan September 21, 2014, 9:41 pm

    Great article. Thanks

  • Stamen Stoychev September 25, 2014, 5:49 pm

    Very good and well explained article!!!

  • Ewald Ertl November 5, 2014, 8:58 am

    Hi Trevor,
    this comment is not directly for this podcast. It is for the whole series you’ve made and inspired by
    the introduction, where you like to have responses πŸ˜‰

    I’m living in Austria and I’m working in the IT Industry for 22 years now ( Just have calculated, when I started πŸ˜‰
    I started testing software on SunOS, later on on Solaris, changed from testing to System Administration and
    Administration of the distributed Software-system of the company I worked for. Later I changed, where I’m still administrating Linux, Solaris and AIX Servers and I’m developing an inhouse framework in C/C++ but
    since some years also some apps in Java.

    On a regular base I read introduction books in Java to get up with the last developments, because our
    customers in the banking sector are not adpoting so fast. We’re happy if Java 1.6 can be used πŸ˜‰

    And gladly I came across you’re podcasts. Now I listen to you, while I’m walking with our dog during
    the weekend and you really enjoy how you present the topics.

    Keep on going, I love this series.

    Wish you all the best

    • Trevor Page November 6, 2014, 10:40 am

      It’s my pleasure Ewald, I’m always amazed at the huge reach that the podcasting platform has. I love to hear from my “international” listeners like yourself. Thanks so much for taking the time to write out that comment and I look forward to bringing more and more great stuff in the future!

  • rama November 10, 2014, 1:43 pm

    very nice… like it

  • Rajiv November 15, 2014, 4:12 am

    I just want to know how to apply eager loading at a particular method call.
    Eg: Hibernate Service Method – will give List, Customer have relationshiop with CustomerAddress table.
    I want to use lazy loading for all method calls inside Service method.
    My problem is,
    I have a webservice method which in turn calls Hibernate Service method and returns the List to the SOAP request, only at this time I want Eager loading and also want to avoid “NullPointerException”.
    Rest of the time, I want Lazy loading only.

    Whats the solution??

    • Trevor Page November 15, 2014, 10:10 am

      Not sure if I fully understand your situation, but maybe this explanation will help you out:

      Eager or Lazy loading is applied (and can only be applied) to the domain classes themselves. You cannot switch between using the Lazy loading and Eager loading strategies dynamically. You must choose and stick to one or the other.

  • hadi January 3, 2015, 3:25 pm

    Nice πŸ™‚

  • Luis January 5, 2015, 3:21 am

    Thanks!!, it helped me a lot.

  • Anonymous January 20, 2015, 10:25 pm

    It’s great. thanks

  • Yan February 7, 2015, 10:50 pm

    Great article. Thank you so much.

  • Antibrumm February 10, 2015, 3:21 am

    Nice article about Lazy loading. However: You are doing one important mistake: The default fetch type of …ToOne relations are EAGER and NOT LAZY (declared in hibernate-jpa-2.1-api-1.0.0.Final.jar) . You can further optimize the sql queries if you turn on lazy loading also for the …ToOne relations, as the generated queries will not contain joins to the already loaded entity.

    public @interface ManyToOne {
    * (Optional) Whether the association should be lazily
    * loaded or must be eagerly fetched. The EAGER
    * strategy is a requirement on the persistence provider runtime that
    * the associated entity must be eagerly fetched. The LAZY
    * strategy is a hint to the persistence provider runtime.
    FetchType fetch() default EAGER;

  • Ilya February 16, 2015, 8:11 pm

    it’s clear now. tnx

  • Paul February 18, 2015, 7:46 am

    You should clarify whatΒ΄s happens when you try to cast an hibernate proxy. You will need initialize that element first to avoid issues.
    I think a little bit explanation about what a hibernate proxy it is would be nice.

  • Mithun March 4, 2015, 4:52 am

    Excellent article. Clearly explained the concepts on Lazy and Eager loading.

  • Rebe March 4, 2015, 9:12 am

    Finally a post on how to load correctly in a Lazy loading context. Thank you.

  • Pierre Roudaut March 26, 2015, 4:29 pm

    @TrevorPage, I just want to give you a big hug πŸ™‚ !

    I’ve been struggling for days to understand the behavior of Hibernate on Set of entities contained in an entity (one-to-many).
    Having a a background in C language, I am used to test every pointer I touch and to control every initialization. So, the limit where Hibernate actually initialize and populate entities for you is actually blurry when you are a beginner using this ORM (such as me).

    I was using lazy loading on an entity that had a collection of other entites (one-to-many), the pointer of the Set was not NULL so I figured the whole Set was initialized and populate but NO !!! As soon as you even iterate on the Set, a LazyLoadingException is thrown.

    After reading this tutorial, I now understand where is the limit of what Hibernate actually does, and where do I need to trigger.
    So thanks a LOT ! You just made it crystal clear !

  • shantanu April 10, 2015, 2:20 pm

    Nice end to the article πŸ˜€

  • Sreekanth April 18, 2015, 11:04 am

    Too useful information..thanks a ton

  • Raunak Shakya May 1, 2015, 6:25 am

    great article, gave me a clear understanding of fetching. thanks a lot!

  • Mark July 24, 2015, 9:25 am

    Great article. Lazy loading can be one of the more confusing things in hibernate and you gave a simple and clear example of how to use it properly.

  • Hassan July 28, 2015, 1:26 am

    Simply great…………..! πŸ™‚

  • Singh July 28, 2015, 8:04 pm

    >>Any time you see a @OneToOne, @OneToMany or @ManyToMany annotations, you’ve got a relationship. What’s important to note is that the fetch type should be specified within those annotations, if you don’t specify one then it defaults to FetchType.LAZY.

    Please note, for @OneToOne and @ManyToOne, default fetch type is FetchType.EAGER

  • bangaram September 26, 2015, 1:56 am

    in real time example where we can used these lazy and early loading
    for example explain amazon applications

  • youssef January 7, 2016, 5:51 am

    Hi, i want just to add somthing that FetchType.LAZY is not the default behaviour for Hibernate annotation relationships.


  • abhishek March 14, 2016, 7:03 am

    nice one, Tx

  • VasyaFortochkin May 19, 2016, 8:15 am

    Thanks, man. You’ve really helped me

  • Srikant Bhushan August 18, 2016, 3:58 am

    very nice clarification of difference between both according to scope of DAO class and Hibernate Session and I understand the same according to DAO class but not getting the difference according to Hibernate Session.

  • Filip September 3, 2016, 4:38 am

    That’s a great article! Thanks

  • Rusli Usman December 22, 2016, 6:44 pm

    Excellent explaination of the EAGER and LAZY fetching. What I’m looking for is the solution to the LAZY type, and your article helps me. Thanks very much.

  • Boris February 28, 2017, 4:45 pm

    Excellent article. Eloquently explains eager and lazy fetch types.
    This piece of art should be served as a template for “how to write technical articles”. Seriously.

  • Alan May 29, 2017, 2:35 pm

    Nice article

  • Anonymous June 7, 2017, 6:34 am


  • Anonymous August 14, 2017, 11:59 am


  • Anonymous October 3, 2017, 3:01 am


  • Anonymous October 3, 2017, 3:01 am


  • sagar March 5, 2018, 5:40 am

    Useful Atricle thanks!

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.