Monday, 11 June 2018

Hibernate Caching: First-Level and Second-Level Cache Explained

       In the previous post, we learned about the different states of an entity in Hibernate. In this post, we will learn about the caching mechanism, including the first-level cache and second-level cache in Hibernate.

What is Caching in Hibernate?

Caching is a mechanism for storing frequently accessed objects in cache memory. The main advantage of caching is that when the same object is requested again, Hibernate retrieves it from the cache instead of querying the database. This reduces the number of round trips between the application and the database server, thereby improving the application's performance.

There are mainly two types of caching in Hibernate:

  • First-Level Cache

  • Second-Level Cache



First Level Cache:-

The first-level cache is associated with the Session object. Its scope is limited to a single Hibernate session. Once the session is closed, all cached objects are removed permanently.

The first-level cache is enabled by default and cannot be disabled. When an entity is queried for the first time within a session, Hibernate retrieves it from the database and stores it in the session's first-level cache. If the same entity is requested again within the same session, Hibernate returns it from the cache instead of executing another SQL query.

A cached entity can be removed from the session using the evict() method. If the same entity is requested again after being evicted, Hibernate will execute a database query to reload it. Similarly, the clear() method removes all entities from the session cache. After calling clear(), Hibernate will fetch entities from the database again when they are requested.

Example

In this example, we will retrieve a Department object from the database using a Hibernate session. We will retrieve the same object multiple times and observe the SQL logs to understand how the first-level cache works.

//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
 
//fetch the department entity from database first time
Department department = (Department) session.load(Department.class, new Integer(1));
System.out.println(department.getName());
 
//fetch the department entity again(second time)
department = (Department) session.load(Department.class, new Integer(1));
System.out.println(department.getName());
 
session.getTransaction().commit();
HibernateUtil.shutdown();
 

Output:

Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
IT
IT


evict() and clear() method in Hibernate:-

evict():  Removes the object from the session. This method is used to dissociate/disconnect the specified object from the session.

clear () :  When this method get called inside transaction boundry then all objects  which are currently associate with particular session will be  disconnected / clean or no longer associate with that Session instance.



Second Level Cache

             The second-level cache is associated with the SessionFactory object. It is created at the SessionFactory level and is shared across all Hibernate sessions created by that SessionFactory. When the SessionFactory is closed, the second-level cache and its associated cache manager are also destroyed.

Whenever a Hibernate session attempts to load an entity, it first checks the first-level cache (which is associated with the current session). If the entity is found there, Hibernate returns it immediately without executing a database query.

If the entity is not found in the first-level cache, Hibernate checks the second-level cache. If the entity exists in the second-level cache, it is returned and also stored in the first-level cache of the current session. This ensures that subsequent requests for the same entity within the same session are served from the first-level cache without accessing the second-level cache again.

If the entity is not found in either the first-level or second-level cache, Hibernate executes a database query to retrieve it. The retrieved entity is then stored in both the first-level cache and the second-level cache (if second-level caching is enabled for that entity) before being returned to the application.

The second-level cache is not enabled by default. Hibernate supports several cache providers that implement the second-level cache, including:

  • Ehcache

  • OSCache

  • SwarmCache

  • JBoss Cache

Each cache provider offers different features and capabilities. Hibernate supports the following cache concurrency strategies:

  • read-only – Suitable for data that never changes. It provides the best performance for read-only entities.

  • nonstrict-read-write – Supports both read and write operations but does not guarantee strong consistency. Occasional stale data may be returned.

  • read-write – Supports both read and write operations while maintaining data consistency through appropriate locking mechanisms.

  • transactional – Provides transactional cache access and is intended for environments that support JTA transactions.

Example

In the following example, we will configure and use Ehcache as the provider for Hibernate's second-level cache.

hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>  
<!DOCTYPE hibernate-configuration PUBLIC  
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
    
<hibernate-configuration>  
  
    <session-factory>  
        <property name="show_sql">true</property>  
        <property name="hbm2ddl.auto">update</property>  
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>  
        <property name="connection.url">jdbc:mysql://localhost/sample</property>  
        <property name="connection.username">root</property>  
        <property name="connection.password">root</property>  
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>  
        
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>  
        <property name="hibernate.cache.use_second_level_cache">true</property>  
       
    </session-factory>  
  
</hibernate-configuration>

SampleTest.java,

package com.adnblog;  
  
import org.hibernate.Session;  
import org.hibernate.SessionFactory;  
import org.hibernate.cfg.Configuration;  
  
public class SampleTest {  
     public static void main(String[] args) {  
          Configuration cfg=new Configuration().configure("hibernate.cfg.xml");  
          SessionFactory factory=cfg.buildSessionFactory();  
      
          Session session1=factory.openSession();  
          Student std1=(Student)session1.load(Student.class,121);  
          System.out.println(std1.getId()+" "+std1.getName());  
          session1.close();  
      
          Session session2=factory.openSession();  
          Student std2=(Student)session2.load(Student.class,121);  
          System.out.println(std2.getId()+" "+std2.getName());  
          session2.close();  
      
     }  
}  
  
Output :--  select student0_.id as id0_0, student0_.name as name0_0 from STUDENT student0_ where student0_.id = ?
                   18 Mahesh M
                   18 Mahesh M

Thank you for visiting blog.



Related Post:-
1) What are different states of an entity bean in Hibernate?
2) Hibernate One to One Mapping Example - Annotation based
3) Hibernate - JPA Annotations with explanation
4) Advantages of Hibernate over JDBC
5) What are the Core Interfaces of Hibernate framework ?
6) Spring MVC with Hibernate CRUD Example

No comments:

Post a Comment