Java and J2EE Tutorials, Jsp and Servlet Tutorials, Spring MVC, Solr, XML, JSON Examples, Hibernate & Struts 2 Hello World projects



Saturday, 15 November 2014

How First Level Caching Works in Hibernate - Example

In computer science Caching is a practice that stores data in memory to increase performance by reducing the number of database hits. In a caching procedure we stores frequently asked data into memory so than next time a similar request came to the application the data can be served from the cache memory without fetching it again and again from the database. It helps us to reduce the number of database hits and hence increases performance.


Caching in Hibernate

While Hibernate proved itself an efficient and useful tool in Java community, it provides three type of in build caching techniques, we call them First level caching, Second level caching and Query Caching.


First Level Caching in Hibernate

First Level Caching is enabled by default and we don’t need to do anything to achieve it, in fact we can’t even disable it from there. First level caching is also called Session Level Caching meaning that it works for a session only, in case same query is being executed two or more times in a single session it gets data from the DB for the very first request only and serves the same data from cache for all upcoming similar requests.


How First Level Caching Works in Hibernate

First level cache is associated with sessions only, when the query is executed first time it gets the data from the database and save that data to cache memory. The data that is stored in cache at first occurrence of query is being served for all upcoming similar requests until the session is alive.



Once a session is closed all first level cache are cleared. We can remove a particular loaded entity from the cache using evict() and entire cache can be cleared using clear(). Once the cache is cleared with any of the two methods it will query to the database again for a new call even if the session is not closed yet.

src\main\java\com\beingjavaguys\sample\CachingImpl.java
package com.beingjavaguys.sample;

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

import com.beingjavaguys.models.Employee;
import com.beingjavaguys.utils.HibernateUtils;

/**
 * @author Nagesh.Chauhan
 *
 */
public class CachingImpl {
 public static void main(String[] args) {
  SessionFactory sessionFactory = HibernateUtils.getSessionFactory();

  // create an employee object to persist in DB
  Employee employee = new Employee("eddy", "smith",
    "eddy@beingjavaguys.com", "9898787676");

  // lets save few data in Employee table
  Session session = sessionFactory.openSession();
  Transaction transaction = session.beginTransaction();
  session.save(employee);
  transaction.commit();
  session.close();

  System.out.println("****Data creation completed****");

  Session session1 = sessionFactory.openSession();
  System.out.println("****Created Session 1****");
  transaction = session1.beginTransaction();

  employee = (Employee) session1.load(Employee.class, 1l);
  System.out.println(employee.getFirstName());

  employee = (Employee) session1.load(Employee.class, 1l);
  System.out.println(employee.getFirstName());

  employee = (Employee) session1.load(Employee.class, 1l);
  System.out.println(employee.getFirstName());

  transaction.commit();
  session1.close();
  System.out.println("****Closed Session 1****");

  Session session2 = sessionFactory.openSession();
  System.out.println("****Created Session 2****");
  transaction = session2.beginTransaction();

  employee = (Employee) session2.load(Employee.class, 1l);
  System.out.println(employee.getFirstName());

  transaction.commit();
  session2.close();
  System.out.println("****Closed Session 2****");

 }
}

****Created Session 1****
Hibernate: select employee0_.ID as ID1_0_0_, employee0_.EMAIL as EMAIL2_0_0_, employee0_.FIRST_NAME as FIRST_NA3_0_0_, employee0_.LAST_NAME as LAST_NAM4_0_0_, employee0_.PHONE as PHONE5_0_0_ from EMPLOYEE employee0_ where employee0_.ID=?
eddy
eddy
eddy
****Closed Session 1****
****Created Session 2****
Hibernate: select employee0_.ID as ID1_0_0_, employee0_.EMAIL as EMAIL2_0_0_, employee0_.FIRST_NAME as FIRST_NA3_0_0_, employee0_.LAST_NAME as LAST_NAM4_0_0_, employee0_.PHONE as PHONE5_0_0_ from EMPLOYEE employee0_ where employee0_.ID=?
eddy
****Closed Session 2****


You can see that for session1 we have requested the entity three times but the query is being executed only once and for second and third request the data saved in the cache is served. We closed the session1 and created new session2, this time we requested same entity from database but it went to get data from DB because the cached data is cleared when session1 get closed. Here is what happened.

1) We requested for the Employee entity first time, hibernate checked if the object is available on first level cache; the object is not there so the entity is requested from the database. And a copy of that is stored on cache.

2) Now second request came for employee entity, this time the entity was present on cache so no db call made and entity served from the cache.

3) Now third request came for employee entity, this time the entity was present on cache so no db call made and entity served from the cache.

4) Session (session1) is closed so all the first level cache data associated with is removed.

5) A new session (session2) being created.

6) A request came to get employee entity, hibernate checked if the object is available on first level cache, the object is not there so the entity is requested from form the database. And a copy of that is stored on cache.


How evict() and clear() works in hibernate

We can’t disable first level cache in hibernate but we can clear a particular entity cache with evict() and whole cache with clear(). The example below explains the same.

src\main\java\com\beingjavaguys\sample\EvictImpl.java
package com.beingjavaguys.sample;

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

import com.beingjavaguys.models.Employee;
import com.beingjavaguys.utils.HibernateUtils;

/**
 * @author Nagesh.Chauhan
 *
 */
public class EvictImpl {
 public static void main(String[] args) {
  SessionFactory sessionFactory = HibernateUtils.getSessionFactory();

  // create an employee object to persist in DB
  Employee employee = new Employee("eddy", "smith",
    "eddy@beingjavaguys.com", "9898787676");

  // lets save few data in Employee table
  Session session = sessionFactory.openSession();
  Transaction transaction = session.beginTransaction();
  session.save(employee);
  transaction.commit();
  session.close();

  System.out.println("****Data creation completed****");

  Session session1 = sessionFactory.openSession();
  System.out.println("****Created Session****");
  transaction = session1.beginTransaction();

  employee = (Employee) session1.load(Employee.class, 1l);
  System.out.println(employee.getFirstName());

  employee = (Employee) session1.load(Employee.class, 1l);
  System.out.println(employee.getFirstName());

  // removed employee entity from the cache
  session1.evict(employee);
  System.out.println("****removed employee entity from the cache****");

  employee = (Employee) session1.load(Employee.class, 1l);
  System.out.println(employee.getFirstName());

  transaction.commit();
  session1.close();
  System.out.println("****Closed Session****");

 }
}

****Created Session****
Hibernate: select employee0_.ID as ID1_0_0_, employee0_.EMAIL as EMAIL2_0_0_, employee0_.FIRST_NAME as FIRST_NA3_0_0_, employee0_.LAST_NAME as LAST_NAM4_0_0_, employee0_.PHONE as PHONE5_0_0_ from EMPLOYEE employee0_ where employee0_.ID=?
eddy
eddy
****removed employee entity from the cache****
Hibernate: select employee0_.ID as ID1_0_0_, employee0_.EMAIL as EMAIL2_0_0_, employee0_.FIRST_NAME as FIRST_NA3_0_0_, employee0_.LAST_NAME as LAST_NAM4_0_0_, employee0_.PHONE as PHONE5_0_0_ from EMPLOYEE employee0_ where employee0_.ID=?
eddy
****Closed Session****


We can see that, we requested employee entity three times again, here is what happened :

1) We requested for the Employee hibernate checked if the object is available on first level cache, the object is not there so the entity is requested from form the database. And a copy of that is stored on cache.

2) Next time same request came for employee entity, this time the entity was present on cache so no db call made and entity served from the cache.

3) A request came to remove entity from the cache, now cache does not have a cached entity.

4) Third request came to get employee entity, hibernate checked if the object is available on first level cache, the object is not there so the entity is requested from form the database. And a copy of that is stored on cache. We look into how evict() works for hibernate, clear works in the same way except that clear() removes all the entities form the cache.


Here we are done with how first level cache works in hibernate and how evict() and clear() works in hibernate. We came to know how we can clear hibernate cache using evict() and clear(). In coming articles we will see how to what is second level caching and query caching in hibernate.

Complete Source Code and Configuration can be found in the attached sample project. Download it from Here: Download Source Code









Thanks for reading !
Being Java Guys Team

Download How First Level Caching Works in Hibernate Project






3 comments:

  1. Simple and clear

    ReplyDelete
  2. Well explained. Hopefully Hibernate Session can also be bound by thread to make first level cache thread safe

    ReplyDelete

Like Us on Facebook


Like Us On Google+



Contact

Email: neel4soft@gmail.com
Skype: neel4soft