Tutorial

Hibernate Caching - First Level Cache

Published on August 4, 2022
author

Pankaj

Hibernate Caching - First Level Cache

Welcome to Hibernate Caching - First Level Cache Example Tutorial. Recently we looked into Hibernate architecture, hibernate mapping and how to use HQL for firing SQL queries in object oriented way. Today we will look into one of the important aspects of Hibernate - Hibernate Cache.

Hibernate Caching

hibernate caching, hibernate cache, first level cache in hibernate Hibernate Cache can be very useful in gaining fast application performance if used correctly. The idea behind cache is to reduce the number of database queries, hence reducing the throughput time of the application. Hibernate comes with different types of Cache:

  1. First Level Cache: Hibernate first level cache is associated with the Session object. Hibernate first level cache is enabled by default and there is no way to disable it. However hibernate provides methods through which we can delete selected objects from the cache or clear the cache completely. Any object cached in a session will not be visible to other sessions and when the session is closed, all the cached objects will also be lost.
  2. Second Level Cache: Hibernate Second Level cache is disabled by default but we can enable it through configuration. Currently EHCache and Infinispan provides implementation for Hibernate Second level cache and we can use them. We will look into this in the next tutorial for hibernate caching.
  3. Query Cache: Hibernate can also cache result set of a query. Hibernate Query Cache doesn’t cache the state of the actual entities in the cache; it caches only identifier values and results of value type. So it should always be used in conjunction with the second-level cache.

Hibernate Caching - First Level Cache Example

For my hibernate first level cache example program, I am using same configuration as in HQL Example, you can check that out and configure the tables and populate it with dummy data. Let’s first look into the program, it’s output and then we will go through some of the important points related to Hibernate First Level Cache. HibernateCacheExample.java

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateCacheExample {

	public static void main(String[] args) throws InterruptedException {
		
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		//Get employee with id=1
		Employee emp = (Employee) session.load(Employee.class, new Long(1));
		printData(emp,1);
		
		//waiting for sometime to change the data in backend
		Thread.sleep(10000);
		
		//Fetch same data again, check logs that no query fired
		Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp1,2);
		
		//Create new session
		Session newSession = sessionFactory.openSession();
		//Get employee with id=1, notice the logs for query
		Employee emp2 = (Employee) newSession.load(Employee.class, new Long(1));
		printData(emp2,3);
		
		//START: evict example to remove specific object from hibernate first level cache
		//Get employee with id=2, first time hence query in logs
		Employee emp3 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp3,4);
		
		//evict the employee object with id=1
		session.evict(emp);
		System.out.println("Session Contains Employee with id=1?"+session.contains(emp));

		//since object is removed from first level cache, you will see query in logs
		Employee emp4 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp4,5);
		
		//this object is still present, so you won't see query in logs
		Employee emp5 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp5,6);
		//END: evict example
		
		//START: clear example to remove everything from first level cache
		session.clear();
		Employee emp6 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp6,7);
		Employee emp7 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp7,8);
		
		System.out.println("Session Contains Employee with id=2?"+session.contains(emp7));
		
		tx.commit();
		sessionFactory.close();
	}

	private static void printData(Employee emp, int count) {
		System.out.println(count+":: Name="+emp.getName()+", Zipcode="+emp.getAddress().getZipcode());
	}

}

When we run above example, the output contains a lot of hibernate related information. But we are mostly interested in our code specific output and the queries fired by hibernate to load the data. The output snippet looks like below.

Hibernate Configuration loaded
Hibernate serviceRegistry created
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
1:: Name=Pankaj, Zipcode=95129
2:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
3:: Name=PankajK, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
4:: Name=David, Zipcode=95051
Session Contains Employee with id=1?false
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
5:: Name=Pankaj, Zipcode=95129
6:: Name=David, Zipcode=95051
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
7:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
8:: Name=David, Zipcode=95051
Session Contains Employee with id=2?true

First Level Cache in Hibernate Important Points

Important Points about First level cache in Hibernate that can be derived from above program are:

  1. Hibernate First Level cache is enabled by default, there are no configurations needed for this.
  2. Hibernate first level cache is session specific, that’s why when we are getting the same data in same session there is no query fired whereas in other session query is fired to load the data.
  3. Hibernate first level cache can have old values, as you can see above that I have put my program to sleep for 10 seconds and in that time I updated the value (name from Pankaj to PankajK) in database but it didn’t get reflected in the same session. But in other session, we got the updated value.
  4. We can use session evict() method to remove a single object from the hibernate first level cache.
  5. We can use session clear() method to clear the cache i.e delete all the objects from the cache.
  6. We can use session contains() method to check if an object is present in the hibernate cache or not, if the object is found in cache, it returns true or else it returns false.
  7. Since hibernate cache all the objects into session first level cache, while running bulk queries or batch updates it’s necessary to clear the cache at certain intervals to avoid memory issues.

That’s all for hibernate caching and first level cache example, in future posts we will look into Hibernate Second Level Cache - EHCache implementation.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Pankaj

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
December 29, 2021

It is very good explanation of first level cache. I am reading this first time and I got understood the concept. Thanks

- Saravanank

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    December 17, 2021

    Do you think session cache can lead to data inconsistency with multiple threads working on same data or in case of multiple instance of the application running.

    - veer

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      November 21, 2019

      Loved the example, I can use it for my interviews…

      - jagadish

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        November 12, 2018

        Great example to explain the hibernate first level cache

        - Muthu

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          October 13, 2017

          You should use get method or add comment before print method that query is fired or not because load will never fire a query.And it can confuse new learners.

          - Jaspreet Singh

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            April 14, 2017

            Isn’t printData(emp4,5); supposed to show name as PankajK as it is hitting database where data was updated earlier during Thread.sleep(10000). Correct me if I am wrong.

            - Rohit Roy

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              February 12, 2017

              Very Clearly explaind, on the first read it was little bit confusing but eventually ended with a very good explanantion.

              - Vijay Raj R

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                July 14, 2016

                Is criteria uses the cache technique or only get() and load() with will use it.

                - Aj

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  June 17, 2016

                  Nice explanation…

                  - Ram

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    March 18, 2015

                    I am getting following error when I try to runt the program. Can you please provide the solution? org.hibernate.AnnotationException: Unknown mappedBy in: com.test.model.Employee.address, referenced property unknown: com.test.model.Address.employee at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:153) at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846) at com.test.util.HibernateUtilities.buildAnnotationSessionFactory(HibernateUtilities.java:52) at com.test.util.HibernateUtilities.getSessionAnnotationFactory(HibernateUtilities.java:99) at com.test.HibernateCacheExample.main(HibernateCacheExample.java:14)

                    - Chintan

                      Try DigitalOcean for free

                      Click below to sign up and get $200 of credit to try our products over 60 days!

                      Sign up

                      Join the Tech Talk
                      Success! Thank you! Please check your email for further details.

                      Please complete your information!

                      Become a contributor for community

                      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                      DigitalOcean Documentation

                      Full documentation for every DigitalOcean product.

                      Resources for startups and SMBs

                      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                      Get our newsletter

                      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                      New accounts only. By submitting your email you agree to our Privacy Policy

                      The developer cloud

                      Scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Get started for free

                      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                      *This promotional offer applies to new accounts only.