Java @ Desk: Ehcache | Java at your desk

How to Configure EhCache in Hibernate

How to Configure EhCache in Hibernate

As seen in the previous post How to configure EhCache in Java, we will see how to configure ehCache as Second level Cache in Hibernate.
ORM Framework like hibernate provides cache mechanism to avoid number of queries made to database, which in turn increase the performance of web application.

Hibernate provides two layers of cache mechanism –
First Level Cache – Works in Session scope, enabled by default.
Second Level Cache – We need to configure the second level cache and it is available in session factory scope.

In this post we will see how to configure the ehCache as Second Level Cache in Hibernate and store/retrieve elements from second level cache.

Let's Start –
1) What is EhCache – As discussed in previous article ehCache is popular open source java cache mechanism which can be used as second level cache in Hibernate. ehCache can be downloaded from - http://www.terracotta.org/products/enterprise-ehcache. Below is maven dependency for ehCache – net.sf.ehcache ehcache 2.9.1

2) Hibernate configuration -
To download the hibernate 3.3.2.GA version from –
http://sourceforge.net/projects/hibernate/files/hibernate3/3.3.2.GA/

3) Configure EhCache in Hibernate
Steps to enable ehcache in Hibernate -

- Enable ehCache in Hibernate. Need to provide the configure in hibernate.cfg.xml
- Configure the entity object either in hbm.xml files or using annotation by choosing appropriate caching strategy
- Enable query caching mechanism
- If needed define the ehcache.xml to over the default values.

Let's understand by example in detail -

Note : In Order to run the application, you need to download the MySql database and should be working and able to connect. Need to create the database and Table by using below commands, which has been used in hibernate.cgf.xml
create database hibernatedemo
create table TRADE(ID int(10),NAME VARCHAR(50));


1. Hibernate Configuration File
In Order to configure ehcache in hibernate need to perform in two steps –
- Enable second level cache in hibernate.cgf.xml
- Specify the second level cache provider.

<?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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedemo</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">create</property>
<!--         <property name="hibernate.cache.use_second_level_cache">true</property> -->
 <property name="hibernate.cache.use_second_level_cache">true</property>
         <property name="hibernate.cache.use_query_cache">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <mapping class="code.desk.entity.DummyTrade"></mapping>
        
    </session-factory>
</hibernate-configuration>




2. Configure Entity Objects
If we are using hbm.xml file then we can configure as –
<class name=" code.desk.entity.DummyTrade " table="TRADE">
    <cache usage="read-write"/>
</class>

If we are using annotation based configuration then we can use the following code snippet–
In Order to define caching strategy we need to put the following statement
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="dummyTrade")

package code.desk.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
 
@Entity (name = "dept")
@Table(name = "TRADE", uniqueConstraints = {
        @UniqueConstraint(columnNames = "ID"),
        @UniqueConstraint(columnNames = "NAME") })
         
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="dummyTrade")
 
public class DummyTrade implements Serializable {
     
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true, nullable = false)
    private Integer id;
     
    @Column(name = "NAME", unique = true, nullable = false, length = 100)
    private String name;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}


3. Define the EhCache Configuration File
As per the property defined in hibernate.cgf.xml, need to configure ehcache.xml.
<property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property>


As Defined in Cache configuration the cache name should be same as region name defined in DummyTrade entity.
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore path="c:\temp\cache"/>
<cache
    name="dummyTrade"
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="5"
    timeToLiveSeconds="10"
    overflowToDisk="true"
/>
 
</ehcache>


4. Hibernate Utility -
HibernateUtility class use to get the Singleton Instance of SessionFactory.
package code.desk.util;

import java.io.File;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
 
public class HibernateUtility
{
    private static final SessionFactory sessionFactory = buildSessionFactory();
      
    private static SessionFactory buildSessionFactory()
    {
        try
        {
            // Create the SessionFactory from hibernate.cfg.xml
            return new AnnotationConfiguration().configure(new File("hibernate.cgf.xml")).buildSessionFactory();
        }
        catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
  
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
  
    public static void shutdown() {
        // Close caches and connection pools
        getSessionFactory().close();
    }
}


5. Finally Test the Functionality -
In order to understand better I kept example easy and simple. Object stored in first level cache associated with session but objects stored in second level cache remains beyond the session as well.
In the below example, first we load the entity, which triggers database call and store it into the first level cache and second level cache.
When try to load the same entity again, it first look into the first level cache and if found it returns, this doesn't make any database call.
Now in order to test second level cache, we close the first session, which make sure the entity is not getting load from first level cache. Now again create the another session and try to load the entity, you can see the output, it will load from the second level cache and doesn't make the call to database.

Below is the code snippet –
package code.desk.test;

import org.hibernate.Session;
import org.hibernate.stat.Statistics;

import code.desk.entity.DummyTrade;
import code.desk.util.HibernateUtility;

public class TestHibernateEhcacheMain
{  
    public static void main(String[] args)
    {
        insertDataToDB();
        Statistics statistics = HibernateUtility.getSessionFactory().getStatistics();
        try
        {
         // Enable the hibernate statics 
         System.out.println("Is statics enabled "+statistics.isStatisticsEnabled());
         statistics.setStatisticsEnabled(true);
         System.out.println("Is statics enabled "+statistics.isStatisticsEnabled());
            //Open the hibernate session
            Session session = HibernateUtility.getSessionFactory().openSession();
            session.beginTransaction();
             
            //fetch the department entity from database first time
            DummyTrade department = (DummyTrade) session.load(DummyTrade.class, new Integer(1));
            System.out.println(department.getName());
             
            //fetch the department entity again; Fetched from first level cache
            department = (DummyTrade) session.load(DummyTrade.class, new Integer(1));
            System.out.println(department.getName());
            //Let's close the session
            
            session.getTransaction().commit();
            session.close();
            
             
            //Try to get department in new session
            Session anotherSession = HibernateUtility.getSessionFactory().openSession();
            anotherSession.beginTransaction();
             
            //Here entity is already in second level cache so no database query will be hit
            department = (DummyTrade) anotherSession.load(DummyTrade.class, new Integer(1));
            System.out.println(department.getName());
            
            
            anotherSession.getTransaction().commit();
            anotherSession.close();
        }
        finally
        {
            
   System.out.println(statistics.getEntityFetchCount()); //Prints 1
            System.out.println(statistics.getSecondLevelCacheHitCount()); //Prints 1
             
            HibernateUtility.shutdown();
        }
    }
     
    private static void insertDataToDB()
    {
        Session session = HibernateUtility.getSessionFactory().openSession();
        session.beginTransaction();
         
        DummyTrade department = new DummyTrade();
        department.setName("Human Resource");
         
        session.save(department);
        session.getTransaction().commit();
        session.close();
    }
}


This post is written by
Soumitra Pathak - Linkedin, Facebook

He is a freelance writer, loves to explore latest features in Java technology.

EhCache - How to Configure EhCache

EhCache Introduction - How to Configure EhCache

1. What is EhCache – EHCache is a Standard Java Based cache for boosting performance. EhCache is robust, proven and full featured cache mechanism. We can use Ehcache as a general-purpose cache or a second-level cache for Hibernate. It can be integrated with the Hibernate, Spring or any other Java based third party tool.
2. Why EhCache – EhCache is a widely used for Java Distributed Cache for a general purpose caching, Java EE and Application Servers. It features scalable, fast, lightweight, JMX enabled and Distributed caching etc.
3. How to Configure EhCache

Following are the steps to Configure the EhCache for general purpose Caching –

i. Add EhCache JAR to classpath
ii. Provide the configuration using ehcache.xml and place it to classpath
iii. Create a CacheManager
CacheManager cacheManager = new CacheManager();


iv. Reference a Cache
Ehcache sampleCache = cacheManager.getEhcache("SampleCache");


v. Use it
sampleCache.put(new Element("key", "value"));
sampleCache.get("key");


4. Let's Explore
Through the Sample cache code I will try to explain how to configure and use the EhCache.
In coming post we will see how to integrate EhCache with Hibernate, Spring and any database application.

5. Demo Application – Using the Demo Application we will -
Create an Instance of Cache using ehcache.xml and CacheManager
Put the List of employee objects inside the cache first time
Access the cache by generating the random key and check whether the object is inside the cache or not?

i. JAR needed to run the project
http://ehcache.org/downloads/destination?name=ehcache-2.9.0-distribution.tar.gz&bucket=tcdistributions&file=ehcache-2.9.0-distribution.tar.gz

ii. Configure EhCache.xml
<?xml version="1.0" encoding="UTF-8"?>

<ehcache name="DefaultSampleCache">
  <defaultCache
      maxElementsInMemory="10000"
      eternal="false"
      timeToIdleSeconds="120"
      timeToLiveSeconds="120"
      diskSpoolBufferSizeMB="30"
      maxElementsOnDisk="10000000"
      diskExpiryThreadIntervalSeconds="120">
      <persistence strategy="localTempSwap"/>
  </defaultCache>
  <!-- Sample cache named sampleCache
    This cache contains a maximum in memory of 10000 elements, and will expire
    an element if it is idle for more than 5 minutes and lives for more than
    10 minutes.
 
    If there are more than 10000 elements it will overflow to the
    disk cache, which in this configuration will go to wherever java.io.tmp is
    defined on your system. On a standard Linux system this will be /tmp" -->
    
  <cache name="sampleCache" 
  maxEntriesLocalHeap="10000"
  maxEntriesLocalDisk="1000" 
  eternal="false" 
  diskSpoolBufferSizeMB="20"
  timeToIdleSeconds="300" timeToLiveSeconds="600"
  memoryStoreEvictionPolicy="LFU" 
  transactionalMode="off">
  <persistence strategy="localTempSwap" />
 </cache>
</ehcache>


iii. Initializing Cache Configuration and get the Cache Object
public class InitCache {
 
 private CacheManager cacheManager;
 
 public InitCache(){
  cacheManager = CacheManager.getInstance();
 }
 
 public Cache getCache(){
  return cacheManager.getCache("sampleCache");
 }
}




iv. Create a Object to put into the Cache
public class Employee implements Serializable {

 int id;
 String name;
 
 @Override
 public String toString() {
  return "Employee [id=" + id + ", name=" + name + "]";
 }

 public int getId() {
  return id;
 }
 
 public void setId(int id) {
  this.id = id;
 }
 
 public String getName() {
  return name;
 }
 
 public Employee(int id, String name) {
  super();
  this.id = id;
  this.name = name;
 }

 public void setName(String name) {
  this.name = name;
 }
}


v. To Generate the 100 Objects Of Employee and keep as a List
public class EmployeeGenerator {

 public static List<Employee> list  = new ArrayList<Employee>();
 
 public static List<Employee> getAllEmployee(){
  for(int i=0;i<100;i++){
   list.add(new Employee(i, i+"name"));
  }
  return list;
 }
 
}


vi. Sample EHCache - Store the objects inside the cache and get the objects from cache using the key.
public class SampleEhCacheDemo {
 
 public static void main(String[] args) {
  
  InitCache cacheconf = new InitCache();
  
  Cache cache = cacheconf.getCache();
  
  // Put the Initial Employees in the Cache.
  
  List<Employee> allEmployee = EmployeeGenerator.getAllEmployee();
  
  for (Employee employee : allEmployee) {
   cache.put(new Element(employee.getId(), employee));
  }
  
  // Search Employee the randomly generated key –
 
  Random randomgenerator = new Random(110);
  for (int i=0;i<10;i++) {
   System.out.println("======");
   int random = randomgenerator.nextInt(110);
   Element ele = cache.get(random);
   String output = (ele == null ? null : ele.getObjectValue().toString());
   System.out.println("OutPut is "+output);
   System.out.println("Is Key ="+random+" Present in Cache "+ cache.isKeyInCache(random));
   System.out.println("======");
  }
 }

}


Summary – we have seen the basic of EhCache, how to configure EhCache, Put the object inside the cache and get the object back from the cache. Next Post we will see how to configure EhCache with Hibernate.

Tag – Ehcache, Caching, In Memory Caching, Java Caching.

This post is written by
Soumitra Pathak - Linkedin, Facebook

He is a freelance writer, loves to explore latest features in Java technology.