Followers

hb : Cache Implementation in Hibernate

Hibernate Second Level Cache

Hibernate second level cache uses a common cache for all the session object of a session factory. It is useful if you have multiple session objects from a session factory.

SessionFactory holds the second level cache data. It is global for all the session objects and not enabled by default.

Different vendors have provided the implementation of Second Level Cache.

EH Cache
OS Cache
Swarm Cache
JBoss Cache

Each implementation provides different cache usage functionality. There are four ways to use second level cache.

read-only: caching will work for read only operation.
nonstrict-read-write: caching will work for read and write but one at a time.
read-write: caching will work for read and write, can be used simultaneously.
transactional: caching will work for transaction.
The cache-usage property can be applied to class or collection level in hbm.xml file. The example to define cache usage is given below:

<cache usage="read-only" /> 
Let's see the second level cache implementation and cache usage.

3 extra steps for second level cache example using EH cache

1) Add 3 configuration setting in hibernate.cfg.xml file

<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property> 
<property name="hibernate.cache.use_second_level_cache">true</property>

2) Add cache usage setting in hbm file

<cache usage="read-only" /> 

3) Create ehcache.xml file

<?xml version="1.0"?> 
<ehcache> 
 
<defaultCache  
maxElementsInMemory="100"  
eternal="true"/> 
 
</ehcache> 

Hibernate Second Level Cache Example

To understand the second level cache through example, we need to create following pages:

Employee.java
employee.hbm.xml
hibernate.cfg.xml
ehcache.xml

FetchTest.java

To implement second level cache, we need to define cache.provider_class property in the configuration file.

File: ehcache.xml

<?xml version="1.0"?> 
<ehcache> 
<defaultCache  
maxElementsInMemory="100"  
eternal="false"  
timeToIdleSeconds="120"  
timeToLiveSeconds="200" /> 
 
<cache name="com.javatpoint.Employee"  
maxElementsInMemory="100"  
eternal="false"  
timeToIdleSeconds="5"  
timeToLiveSeconds="200" /> 
</ehcache> 

You need to create ehcache.xml file to define the cache property.

defaultCache will be used for all the persistent classes. We can also define persistent class explicitely by using the cache element.

eternal If we specify eternal="true", we don't need to define timeToIdleSeconds and timeToLiveSeconds attributes because it will be handled by hibernate internally. Specifying eternal="false" gives control to the programmer, but we need to define timeToIdleSeconds and timeToLiveSeconds attributes.

timeToIdleSeconds It defines that how many seconds object can be idle in the second level cache.

timeToLiveSeconds It defines that how many seconds object can be stored in the second level cache whether it is idle or not.

Employee.java

package mypack;

public class Employee {
private int id;
private String name;
private float salary;

public Employee() {
          super();
}

public Employee(String name, float salary) {
          super();
          this.name = name;
          this.salary = salary;
}

public int getId() {
          return id;
}
public void setId(int id) {
          this.id = id;
}
public String getName() {
          return name;
}
public void setName(String name) {
          this.name = name;
}
public float getSalary() {
          return salary;
}
public void setSalary(float salary) {
          this.salary = salary;
}
}



employee.hbm.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
          "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

          <hibernate-mapping>
          <class name="mypack.Employee" table="emp">
         <cache usage="read-only" />
          <id name="id">
          <generator class="native"></generator>
          </id>
          <property name="name"  ></property>
          <property name="salary"></property>
         
          </class>
          </hibernate-mapping>

ehcahce.xml

<?xml version="1.0"?>

<ehcache>

<defaultCache maxElementsInMemory="100" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="200" />
<cache name="mypack.Employee" maxElementsInMemory="100" eternal="false" timeToIdleSeconds="5" timeToLiveSeconds="200" />

</ehcache>

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.DerbyDialect</property>
        <property name="connection.url">jdbc:derby://localhost:1527/sample</property>
        <property name="connection.username">app</property>
        <property name="connection.password">app</property>
        <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
     <!-- below tags are for Secondary level cache implementation -->
        <property name="cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property>
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <property name="hibernate.cache.use_second_level_cache">true</property>
    <!-- end -->
   
    <mapping resource="employee.hbm.xml"/>
    </session-factory>

FetchData.java

package mypack;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class FetchTest {
public static void main(String[] args) {
Configuration cfg=new Configuration().configure("hibernate.cfg.xml");
SessionFactory factory=cfg.buildSessionFactory();
         
          Session session1=factory.openSession();
          Employee emp1=(Employee)session1.load(Employee.class,1);
          System.out.println(emp1.getId()+" "+emp1.getName()+" "+emp1.getSalary());
          session1.close();
         
          Session session2=factory.openSession();
          Employee emp2=(Employee)session2.load(Employee.class,1);
          System.out.println(emp2.getId()+" "+emp2.getName()+" "+emp2.getSalary());
          session2.close();
}
}



No comments:

Post a Comment