Guide to Lazy Loading in Hibernate

In an application, Hibernate fetches data from the database either in eager or lazy mode. Lazy loading refers to a strategy where data is loaded lazily on-demand when the application needs to access it.

1. Need for Lazy Loading

Consider one of the common Internet web applications: the online store. The store maintains a catalog of products (call it a Category). At the crudest level, this can be modeled as a Category entity managing a series of Product entities. In a large store, there maybe tens of thousands of products grouped into various overlapping categories.

When a customer visits the store, the categories must be loaded from the database. We probably don’t want the application to load every single one of the product entities representing the tens of thousands of products to be loaded into memory. For a sufficiently large retailer, this might not even be possible, given the amount of physical memory available on the machine.

Even if this was possible, it would probably cripple the performance of the site. Instead, we want only the categories to load. Only when the user drills down into the categories should a subset of the products in that category be loaded from the database.

To manage this problem, Hibernate provides a facility called lazy loading. When lazy loading is enabled, an entity’s associated entities will be loaded only when they are directly requested.

2. Lazy Loading in Action

We have understood the problem, let’s see how lazy loading actually helps with an example. If we consider solving the Category-product problem discussed above then we would be accessing a category in the below manner:

//Following code loads only a single category from the database:
Category category = (Category) session.get(Category.class, new Integer(42));

However, if all products of this category are accessed, and lazy loading is in effect, the products are pulled from the database as needed. For instance, in the following snippet, the associated product objects will be loaded since it is explicitly referenced in the second line.

//Following code loads only a single category from the database
Category category = (Category)session.get(Category.class, new Integer(42));
 
//This code will fetch all products for category 42 from database - "NOW"
Set<Product> products = category.getProducts();

This solves our problem of loading the products only when they are needed.

3. The Default Behavior

Before moving further, it is important to recap the default behavior of lazy loading in the case of using hibernate mappings vs annotations.

The default behavior is to load ‘property values eagerly’ and to load ‘collections lazily’. Contrary to what you might remember if you have used plain Hibernate 2 (mapping files) before, where all references (including collections) are loaded eagerly by default.

  • @OneToMany and @ManyToMany associations are defaulted to LAZY loading; and
  • @OneToOne and @ManyToOne are defaulted to EAGER loading. This is important to remember to avoid any pitfall in future.

4. Enabling Lazy Loading in Hibernate

To enable lazy loading explicitly you must use “fetch = FetchType.LAZY” on an association that you want to lazy load when you are using hibernate annotations.

@OneToMany( mappedBy = "category", fetch = FetchType.LAZY )
private Set<ProductEntity> products; 

Another attribute parallel to "FetchType.LAZY" is "FetchType.EAGER" which is just opposite to LAZY i.e. it will load association entity as well when owner entity is fetched first time.

5. How Hibernate Applies Lazy Loading Behind the Scene

The simplest way that Hibernate can apply lazy load behavior upon the entities and associations is by providing a proxy implementation of them.

Hibernate intercepts calls to the entity by substituting a proxy for it derived from the entity’s class. Where the requested information is missing, it will be loaded from the database before control is ceded to the parent entity’s implementation.

Please note that when the association is represented as a collection class, then a wrapper (essentially a proxy for the collection, rather than for the entities that it contains) is created and substituted for the original collection.

When you access this collection proxy then what you get inside returned proxy collection are not proxy entities; rather they are actual entities.

To check if a lazy object has been initialized in hibernate, we can use following method call:

boolean success = Hibernate.isInitialized(products);

6. Effect of Lazy Loading on Detached Entities

As we know that hibernate can only access the database via a session, So If an entity is detached from the session and when we try to access an association (via a proxy or collection wrapper) that has not yet been loaded, Hibernate throws a LazyInitializationException.

The solution is to ensure either that the entity is made persistent again by attaching it to a session or that all of the fields that will be required are accessed (so they are loaded into entity) before the entity is detached from the session.

That’s all for this simple, yet very important concept i.e. how to load lazy object in hibernate. This can be a question for beginners in hibernate fetching strategies interview questions.

Happy Learning !!

Leave a Comment

  1. I was facing a related problem, I wanted to fetch an entity that has 6 entities which are Lazy loading type, and I was getting empty list.
    Thanks for this information.

    Reply
  2. Hello Lokesh, I have Portfolio and Business Unit Entities. I have used LAZY initialization here on Portfolio so that I will get all business unit of respective portfolio only when needed. However, now I see that when I do businessunit.getName(), lot of queries are executed to fetch businessunit details which is impacting performance.

    Can you let me know how to fix this issue. Marking as EAGER in portfolio also causes performance issue because it loads all the data on load of portfolio object.

    Reply
  3. I am getting this exception: Any Help:

    job aborted for the user user1 due to exception: Version mismatch while modifying object. Id 1212
    job aborted for the user user2 due to exception: org.hibernate.exception.GenericJDBCException: could not prepare statement
    job aborted for the user user3 due to exception: org.hibernate.exception.GenericJDBCException: could not prepare statement
    encountered an error in Job: : javax.ejb.EJBTransactionRolledbackException: org.hibernate.exception.GenericJDBCException: could not prepare statement
    Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement
    Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement
    Caused by: java.sql.SQLException: IJ031070: Transaction cannot proceed: STATUS_MARKED_ROLLBACK

    Reply
    • You cannot disable first level cache, it’s default with hibernate. Only understand how it works.
      Second level cache should be used when your database grows and you need to fetch same data set – multiple times or frequently.

      Reply
  4. Hi Lokesh,

    I am just comparaing it to load v/s no-load theory.

    let’s say i have two sections of UI.In one of them i want to show child data along with parent data and in second UI i am just showing parent data.Then i should write two different calls at database level,one is loading child data and another in loading only parent data.

    How lazy/eager loading can helpful in this case because if i do lazy loading then it will consume more time in first case as it will query later rather than using joins etc. and if i use eager then it will consume time in case 2 as there is no need of child data.

    So the thing is ,I think writing two separate db calls is better than having lazy-eager loading.

    Please let me correct if i am wrong and tell me some cases where eager/lazy loading can be helpful.

    Reply
    • Ankit, you brought up some good points and a valid usecase. In my understanding, lazy or eager loading depends on the basis of situation at hand. There is NO eternal law around it. You are right about two separate queries; a different one for each screen.

      Lazy loading can be helpful in cases where you are dealing with large amount of data (for small number of rows/data practically there is no visible difference and lazy loading should be termed as over-engineering). In most of the situations, we should be good to have data loaded eagerly without compromising any visible performance decrease.

      But if any entity in hibernate has lost of references to other entities, and you really are not going to use that information in most of the scenarios then making them lazy loaded make sense. First could be tiny performance improvement; but second is definitely less number of objects loaded into JVM memory and that is very precious resource in any system. Lazy loading is another way to bring down unused objects inside JVM so use it.

      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? I will not do this.

      Reply
  5. Hi, and thanks for this post.

    Could you bring more details and a short example in the last part of this “how to”, about the LazyInitializationException:

    The part is :

    A little bit of code here would be very helpfull.

    best regards from France

    Reply
  6. Hi, and thanks for this post.

    Could you bring more details and a short example in the last part of this “how to”, about the LazyInitializationException:

    The part is :

    “The cure is to ensure either that the entity is made persistent again by attaching it to a session or that all of the fields that will be required are accessed (so they are loaded into entity) before the entity is detached from the session.”

    A little bit of code here would be very helpfull.

    best regards from France

    Reply
  7. What I wish is to switch from lazy to eager fetching on different parts of my code, depending on the situation.

    E.g.
    Person {
    String name;
    Department dept;
    }

    For example, if I wish to display a single record on screen, lazy loading is great. But when we wish to display a list, eager fetch is more efficient. Because it can join and retrieve all records in one Go. If it’s lazy loading, then you retrieve multiple times. (E.g. department table is queried 10 times if we retrieve 10 records from person table)

    Reply
  8. HI Lokesh ,
    Thanks for sharing such a good concept.I am Working on Spring Hibernate and always struggling with jacson mapper exception -no session kind of exception in following case for eg.
    Please see the below example
    1.MY POJOs
    Class State{
    private String name;

    @OneToMany( mappedBy = “state”, fetch = FetchType.LAZY )
    private Set products;
    ///getter and setters
    }
    Class Disrict{
    private String name;

    @ManyToOne
    private State state
    ///getter and setters
    }

    2.My Dao
    Class MydaoImpl implemnets MyDao{

    public List getStateList(){
    List list=null;
    try{
    Session session=HibernateUtil.getSessionFactory.openSession();
    list=session.createCirteria(State.class).list();
    }
    catch(){
    }
    return list;
    }
    }
    3.My service

    @Transactional
    Class MyServiceImpl implemnets MyService{
    @Autowired MyDao mydao;
    public List getStateList(){
    return maydao.getStateList();
    }
    }

    4.finally my Controller
    Class MyController{
    @autowired MyService myservice;

    @Requestmapping(“/getSates”)
    public @ResponseBody List getAllStates(){
    return myService.getStateList();
    }

    so When I am hitting Url for stateList ..it throws jackson exception ..like no session and i m not able to get the state List in ajax call.

    Please tell me the possible solution for this.I searched and found about @JsonIgnore annotation to be used with @OneToMany Annotation.
    what is the best way to do this.
    thanks
    Hemant

    Reply

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode