Hibernate Eager vs Lazy Fetch Type

byTrevor PageonOctober 25, 2013

Background

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.

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:

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).

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
*/
@Repository
@Transactional
public class UserDao
{
@Autowired
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.
Hibernate.initialize(user.getUserProfile());
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!

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.

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.

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?

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.

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.

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.

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.

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!

Hi,
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.

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.

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;
}

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.

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 !

>>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.

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.