How does Hibernate Second Level Cache Works?


Caching helps to reduce database network call, for executing queries.

First level cache is linked with a session. It is implemented implicitly. First level cache exist only till the session object is there. Once session object is terminated/closed, there will be no cache objects. Second level cache works across multiple sessions objects. It is linked with a session factory. Second level cache objects are available to all the session in a single session factory. These cache objects are terminated when that particular session factory is closed.

Implementing second level caching

We need to add the following dependencies in order to use second level caching.

<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
<dependency>
   <groupId>net.sf.ehcache</groupId>
   <artifactId>ehcache</artifactId>
   <version>2.10.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-ehcache</artifactId>
   <version>5.4.32.Final</version>
</dependency>

Note − hibernate ehcache version number must be same as hibernate version number.

Now, we need to add hibernate configuration file which will enable hibernate to connect to the provided database and use second level caching.

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- JDBC Database connection settings --> <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/demo?useSSL=false</property> <property name="connection.username">root</property> <property name="connection.password">root</property> <!-- JDBC connection pool settings ... using built-in test pool --> <property name="connection.pool_size">4</property> <!-- Echo the SQL to stdout --> <property name="show_sql">true</property> //caching properties <property name="cache.use_second_level_cache">true</property> <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!-- Select our SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">create-drop</property> <!-- name of annotated entity class --> <mapping class="academy.company.Parent"/> </session-factory> </hibernate-configuration>

Example

By default all the entities in java are non-cached. So to enable caching of an entity, we use @Cacheable and @Cache annotations in our entity class Parent −

import org.hibernate.annotations.CacheConcurrencyStrategy; import javax.persistence.*; @Entity @Table( name = " Employee") @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) public class Parent { @Id @GeneratedValue(strategy = GenerationType.AUTO) Long id; @Column(name = "first_name") String firstName; @Column(name = "last_name") String lastName; } Now, let’s check whether second level cache works: import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class Main { public static void main(String[] args) { SessionFactory sessionFactory = new Configuration() .configure("academy/company/hibernate.cfg.xml") .buildSessionFactory(); Session session1 = sessionFactory.openSession(); Parent parent1 = session1.get(Parent.class, 4); System.out.println(parent1.id + " " + parent1.firstName + " " + parent1.lastName); session1.close(); Session session2 = sessionFactory.openSession(); Parent parent2 = session2.get(Parent.class, 4); System.out.println(parent2.id + " " + parent2.firstName + " " + parent2.lastName); session2.close(); } }

Output

Hibernate: select parent0.id as id1, parent0.first_name as first_name1, parent0.last_name as last_name1 from Parent parent0 where parent0.id=?
1 Subash Chopra
1 Subash Chopra

We can clearly see from the console that hibernate executed the query only once during session1. Now when the same query is accessed by session2, it will not make a network call to the database for executing it. Instead since we are using second level cache, it will fetch the cache object from session1.

Updated on: 26-Aug-2022

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements