Hibernate Lazy Loading Tutorial

In any application, hibernate fetches data from databse either in eager or lazy mode. Hibernate lazy loading refer to strategy when data is loaded lazily, on demand.

1. Hibernate lazy loading – why we need it?

Consider one of common Internet web application: the online store. The store maintains a catalog of products. At the crudest level, this can be modeled as a catalog entity managing a series of product entities. In a large store, there may be tens of thousands of products grouped into various overlapping categories.

When a customer visits the store, the catalog must be loaded from the database. We probably don’t want the implementation to load every single one of the 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 catalog to load, possibly with the categories as well. 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 enabled, an entity’s associated entities will be loaded only when they are directly requested.

2. How lazy loading solve above problem

Now when we have understood the problem, let’s understand how lazy loading actually helps in real life. If we consider to solve the problem discussed above then we would be accessing a category (or catalog) in 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 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 solve our problem of loading the products only when they are needed.

3. How to enable lazy loading in hibernate

Before moving further, it is important to recap the default behavior of lazy loading in 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.

Also note that @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.

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

A hibernare lazy load example will look like this:

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

4. How lazy loading works in hibernate

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. You need not to put much pressure on understanding this concept because on runtime it hardly matters.

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

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.

Please drop a comment if something is not clear OR you want to discuss anything.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

14 thoughts on “Hibernate Lazy Loading Tutorial”

  1. 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
  2. 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
  3. 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
  4. 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
  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 :

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

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.