Monday, July 28, 2014

Second level Cache in Hibernate

Hibernate second level cache are important for performance perspective. A second level cache is a process specific cache and is shared by all the individual session running in different threads. The data points which are good candidates for caching are:
  • Data which never change, like list of countries, timezone,role types etc.
  • Data that rarely change. (A more changing data in cache will lead to Hibernate doing more work as it has to write to database and has to take care of objects in cache).
To enable the cahce first we need to enable some properties in configuration. I am showing an
example for properties as in Spring environment but same can be adapted for any other environment like as in persistence.xml
In Spring:
<!-- Enabling second level cache for hibernate -->

<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>

<!-- prop key="hibernate.cache.region.factory_class">

net.sf.ehcache.hibernate.EhCacheRegionFactory</prop -->

<!-- prop key="hibernate.cache.region.factory_class">

net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory</prop -->
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>

In persistence.xml 
<!-- Enabling second level cache for hibernate -->
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" />
<!-- prop key="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory/ -->
<!-- prop key="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory/ -->
<property name="hibernate.cache.provider_configuration_file_resource_path" value="ehcache.xml" />
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache " value="true"/>

Note the commented secion of cache provider. The commented secion is as per EhCache document but I could not get it work.
After that a configuration XML need to be provided in the classpath, which in this example is ehcache.xml. A sample ehcache.xml looks like
 <?xml version="1.0" encoding="UTF-8"?>
    <!-- Required elements -->

    <diskStore path="" />

    <defaultCache maxElementsInMemory="25000" eternal="false"

        timeToIdleSeconds="300" timeToLiveSeconds="300" overflowToDisk="true"

        diskPersistent="false" diskExpiryThreadIntervalSeconds="300"

        memoryStoreEvictionPolicy="LRU" />
    <cache name="com.lalit.domain.Role" eternal="true"
        maxElementsInMemory="10" />

Here we are hooking Role object to be put in cache. The eternal is true as we do not expect role object to ever change so we can keep it always in cache. This might change based on your requirements.
Now the last part is to tell the Role object that it needs to participate in cache. For that

@Table(name = "app_roles")

@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)

public class Role{

You might want to change your CacheConcurrencyStretegy based on your need. To make sure that the Cache is working fine, run the app with hibernate logging level at DEBUG. And you should be able to see logging statements like "Cache hit".
More write-ups on Hibernate

No comments:

Post a Comment