Thursday, July 25, 2013

Hibernate Caching - First Level Cache

Caching is one of the basic feature provided by ORM frameworks. Caching make the application to run faster by reducing number of queries to the database. Hibernate provides two levels of cache for this.
  1. First Level Cache: First level cache is associated with each session. This cache is by default and you cannot switch off this. As we can create sessions on demand, there will be first level cache associated with each session.
  2. Second Level Cache: Second level cache is associated with Session Factory. Basically, there is only one second level cache as only one Session Factory is maintained by application.
When a session is closed, the first level cache associated with it will be cleared. When a session factory is cleared, full second level cache associated with it will be lost.

Example for First level cache:

   SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
   Session session = sessionFactory.openSession();
        
   Employee emp = null;
   emp = (Employee) session.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   emp = (Employee) session.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   Session newSession = sessionFactory.openSession();
   emp = (Employee) newSession.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   session.evict(emp);
   emp = (Employee) session.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   newSession.clear();
   emp = (Employee) newSession.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
The log for the above program will be :
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name
Employee Name : name
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name

Explanation:
First time when load method called, the object is fetched by firing a query to database. When the second time loaded, no query was fired as the object is cached in first level cache.
Even though the object is cached by session "session", the new session "newSession" is fetched the object by firing a new query.
To clear the cache from the session, evict() or clear() method can be used. Once it's cleared, the session tries to get the object from the database. The last two queries of hibernate in the log explains that.

Notes:

  • First level cache is only associated to Session. Each session will have it's own first level cache.
  • There is no extra configuration required for first level cache. No way to switch off configuration.
  • Cache will be cleared by closing the session, by using clear() method.
  • Individual object can be removed from the cache by using evict method.