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.

<span class="com"><!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache --></span><span class="pln">
</span><span class="tag"><dependency></span><span class="pln">
   </span><span class="tag"><groupId></span><span class="pln">net.sf.ehcache</span><span class="tag"></groupId></span><span class="pln">
   </span><span class="tag"><artifactId></span><span class="pln">ehcache</span><span class="tag"></artifactId></span><span class="pln">
   </span><span class="tag"><version></span><span class="pln">2.10.9.2</span><span class="tag"></version></span><span class="pln">
</span><span class="tag"></dependency></span><span class="pln">
</span><span class="com"><!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache --></span><span class="pln">
</span><span class="tag"><dependency></span><span class="pln">
   </span><span class="tag"><groupId></span><span class="pln">org.hibernate</span><span class="tag"></groupId></span><span class="pln">
   </span><span class="tag"><artifactId></span><span class="pln">hibernate-ehcache</span><span class="tag"></artifactId></span><span class="pln">
   </span><span class="tag"><version></span><span class="pln">5.4.32.Final</span><span class="tag"></version></span><span class="pln">
</span><span class="tag"></dependency></span>

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.

<div class="code-mirror  language-java" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token operator"><</span><span class="token operator">!</span>DOCTYPE hibernate<span class="token operator">-</span>configuration PUBLIC
   <span class="token string">"-//Hibernate/Hibernate Configuration DTD 3.0//EN"</span>
   <span class="token string">"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"</span><span class="token operator">></span>
<span class="token operator"><</span>hibernate<span class="token operator">-</span>configuration<span class="token operator">></span>
   <span class="token operator"><</span>session<span class="token operator">-</span>factory<span class="token operator">></span>
      <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> JDBC <span class="token class-name">Database</span> connection settings <span class="token operator">--</span><span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"connection.driver_class"</span><span class="token operator">></span><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>mysql<span class="token punctuation">.</span>cj<span class="token punctuation">.</span>jdbc<span class="token punctuation">.</span></span>Driver</span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"connection.url"</span><span class="token operator">></span>jdbc<span class="token operator">:</span>mysql<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>localhost<span class="token operator">:</span><span class="token number">3306</span><span class="token operator">/</span>demo<span class="token operator">?</span>useSSL<span class="token operator">=</span><span class="token boolean">false</span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"connection.username"</span><span class="token operator">></span>root<span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"connection.password"</span><span class="token operator">></span>root<span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> JDBC connection pool settings <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> using built<span class="token operator">-</span>in test pool <span class="token operator">--</span><span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"connection.pool_size"</span><span class="token operator">></span><span class="token number">4</span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> <span class="token class-name">Echo</span> the SQL <span class="token keyword">to</span> <span class="token namespace">stdout</span> <span class="token operator">--</span><span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"show_sql"</span><span class="token operator">></span><span class="token boolean">true</span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token comment">//caching properties</span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"cache.use_second_level_cache"</span><span class="token operator">></span><span class="token boolean">true</span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"cache.region.factory_class"</span><span class="token operator">></span><span class="token class-name"><span class="token namespace">org<span class="token punctuation">.</span>hibernate<span class="token punctuation">.</span>cache<span class="token punctuation">.</span>ehcache<span class="token punctuation">.</span></span>EhCacheRegionFactory</span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> <span class="token class-name">Select</span> our SQL dialect <span class="token operator">--</span><span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"dialect"</span><span class="token operator">></span><span class="token class-name"><span class="token namespace">org<span class="token punctuation">.</span>hibernate<span class="token punctuation">.</span>dialect<span class="token punctuation">.</span></span>MySQL5Dialect</span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> <span class="token class-name">Drop</span> and re<span class="token operator">-</span>create the database schema on startup <span class="token operator">--</span><span class="token operator">></span>
      <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"hbm2ddl.auto"</span><span class="token operator">></span>create<span class="token operator">-</span>drop<span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span>
      <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> name of annotated entity <span class="token keyword">class</span> <span class="token operator">--</span><span class="token operator">></span>
      <span class="token operator"><</span>mapping <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"academy.company.Parent"</span><span class="token operator">/</span><span class="token operator">></span>
   <span class="token operator"><</span><span class="token operator">/</span>session<span class="token operator">-</span>factory<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>hibernate<span class="token operator">-</span>configuration<span class="token operator">></span>
</div>

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 ?

<div class="code-mirror  language-java" contenteditable="plaintext-only" spellcheck="false" style="outline: none; overflow-wrap: break-word; overflow-y: auto; white-space: pre-wrap;"><span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>hibernate<span class="token punctuation">.</span>annotations<span class="token punctuation">.</span></span><span class="token class-name">CacheConcurrencyStrategy</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">javax<span class="token punctuation">.</span>persistence<span class="token punctuation">.</span></span><span class="token operator">*</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Entity</span>
<span class="token annotation punctuation">@Table</span><span class="token punctuation">(</span> name <span class="token operator">=</span> <span class="token string">" Employee"</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@Cacheable</span>
<span class="token annotation punctuation">@org.hibernate.annotations.Cache</span><span class="token punctuation">(</span>usage <span class="token operator">=</span> <span class="token class-name">CacheConcurrencyStrategy</span><span class="token punctuation">.</span>READ_ONLY<span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Parent</span> <span class="token punctuation">{</span>
   <span class="token annotation punctuation">@Id</span>
   <span class="token annotation punctuation">@GeneratedValue</span><span class="token punctuation">(</span>strategy <span class="token operator">=</span> <span class="token class-name">GenerationType</span><span class="token punctuation">.</span>AUTO<span class="token punctuation">)</span>
   <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
   <span class="token annotation punctuation">@Column</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">"first_name"</span><span class="token punctuation">)</span>
   <span class="token class-name">String</span> firstName<span class="token punctuation">;</span>
   <span class="token annotation punctuation">@Column</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">"last_name"</span><span class="token punctuation">)</span>
   <span class="token class-name">String</span> lastName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token class-name">Now</span><span class="token punctuation">,</span> let?s check whether second level cache works<span class="token operator">:</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>hibernate<span class="token punctuation">.</span></span><span class="token class-name">Session</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>hibernate<span class="token punctuation">.</span></span><span class="token class-name">SessionFactory</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token namespace">org<span class="token punctuation">.</span>hibernate<span class="token punctuation">.</span>cfg<span class="token punctuation">.</span></span><span class="token class-name">Configuration</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Main</span> <span class="token punctuation">{</span>
   <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token class-name">SessionFactory</span> sessionFactory <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Configuration</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
         <span class="token punctuation">.</span><span class="token function">configure</span><span class="token punctuation">(</span><span class="token string">"academy/company/hibernate.cfg.xml"</span><span class="token punctuation">)</span>
         <span class="token punctuation">.</span><span class="token function">buildSessionFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token class-name">Session</span> session1 <span class="token operator">=</span> sessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token class-name">Parent</span> parent1 <span class="token operator">=</span> session1<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token class-name">Parent</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>parent1<span class="token punctuation">.</span>id <span class="token operator">+</span> <span class="token string">" "</span> <span class="token operator">+</span> parent1<span class="token punctuation">.</span>firstName <span class="token operator">+</span> <span class="token string">" "</span> <span class="token operator">+</span> parent1<span class="token punctuation">.</span>lastName<span class="token punctuation">)</span><span class="token punctuation">;</span>
      session1<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
      <span class="token class-name">Session</span> session2 <span class="token operator">=</span> sessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token class-name">Parent</span> parent2 <span class="token operator">=</span> session2<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token class-name">Parent</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">      System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>parent2<span class="token punctuation">.</span>id <span class="token operator">+</span> <span class="token string">" "</span> <span class="token operator">+</span> parent2<span class="token punctuation">.</span>firstName <span class="token operator">+</span> <span class="token string">" "</span> <span class="token operator">+</span> parent2<span class="token punctuation">.</span>lastName<span class="token punctuation">)</span><span class="token punctuation">;</span>
      session2<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</div>

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: 2022-08-26T11:24:31+05:30

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements