Friday 4 September 2020

Second Level Cache Configuration in Hibernate 5


 Second Level Cache Configuration in Hibernate 5 


Caching is used to enhance the performance of application . Cache create an in memory storage location(memory buffer) to store recently used data item or objects . when hibernate first time fetch an object from database then hibernate store it in cache memory for future use . if same object require one more time in application then hibernate retrieved from cache memory and no database fetch required that's why it reduced the database query which exceed the performance of application.


Hibernate have three type of cache 

First Level Cache  : First level cache use by hibernate Session it by default enable .

Second Level Cache :Second level use by SessionFactory it require configuration . 
To enable second level cache hibernate require the cache provider vendor .
in our application we have used EHCache vendor implementation .

 EHCache : It can cache in memory or on disk and clustered caching and it
supports the optional Hibernate query result cache.

Second Level Query Cahche : In Hibernate we can fetch object from using hibernate method or using hibernate query language .
if you fetching object using HQL Query then create Query  by setting query cache able true .

Query<Employee> query = session.createQuery("FROM Employee" ,Employee.class); 
query.setCacheable(Boolean.TRUE);
List<Employee> employees =query.getResultList();
 
 

Maven Depedpendcy for EHCache vendor :

<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.2.10.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.4.0</version>
</dependency>

Add following properties in config 

// Second Level Cache Config
Environment.USE_SECOND_LEVEL_CACHE  =  Boolean.toString(Boolean.TRUE)
Environment.CACHE_REGION_FACTORY,   =  "org.hibernate.cache.ehcache.EhCacheRegionFactory"
Environment.CACHE_PROVIDER_CONFIG =   "net.sf.ehcache.hibernate.EhCacheProvider"

Hibernate Entity Class  
Add @Cacheable annotation at class . you can specify optional cache concurrency scheme by @Cache Annotation

Employee.java

package in.jk.hibernate5.second.level.cache;

import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name="hibernate5_second_level_cache_employee")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
@Column(name = "emp_id")
private int empId;
@Column(name = "name")
    private String name;
@Column(name = "company")
    private String company;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", name=" + name + ", company=" + company + "]";
}
}

Hibernate Config class :

package in.jk.hibernate5;

import java.util.HashMap;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;
import in.jk.hibernate5.example.Employee;
import in.jk.hibernate5.onetoone.mapping.Address;
import in.jk.hibernate5.onetoone.mapping.User;

public class HibernateUtils {

private static StandardServiceRegistry standardServiceRegistry = null;
private static SessionFactory sessionFactory = null;

       public static SessionFactory getSessionFactory() {

return sessionFactory;

}

// SessionFactory using java config
public static SessionFactory buildSessionFactory() {

StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();
Map<String, String> hibernateProperties = new HashMap<String, String>();

hibernateProperties.put(Environment.DRIVER, "org.postgresql.Driver");
hibernateProperties.put(Environment.URL, "jdbc:postgresql://localhost:5432/postgres");
hibernateProperties.put(Environment.USER, "postgres");
hibernateProperties.put(Environment.PASS, "jk123");
hibernateProperties.put(Environment.DIALECT, "org.hibernate.dialect.PostgreSQLDialect");
hibernateProperties.put(Environment.SHOW_SQL, "true");
hibernateProperties.put(Environment.HBM2DDL_AUTO, "update");

// Second Level Cache Config
hibernateProperties.put(Environment.USE_SECOND_LEVEL_CACHE,         Boolean.toString(Boolean.TRUE));
hibernateProperties.put(Environment.USE_QUERY_CACHE, Boolean.toString(Boolean.TRUE));

hibernateProperties.put(Environment.CACHE_REGION_FACTORY, "org.hibernate.cache.ehcache.EhCacheRegionFactory");
hibernateProperties.put(Environment.CACHE_PROVIDER_CONFIG, "net.sf.ehcache.hibernate.EhCacheProvider");

serviceRegistryBuilder.applySettings(hibernateProperties);
standardServiceRegistry = serviceRegistryBuilder.build();
MetadataSources metadataSources = new MetadataSources(standardServiceRegistry);

      // Second Level Cache
metadataSources.addAnnotatedClass(in.jk.hibernate5.second.level.cache.Employee.class);
               
                Metadata metadata = metadataSources.getMetadataBuilder().build();
               sessionFactory = metadata.getSessionFactoryBuilder().build();
               return sessionFactory;

}

}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Hibernate5withJava</groupId>
<artifactId>Hibernate5withJava</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.10.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/postgresql/postgresql -->
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.0-801.jdbc4</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.2.10.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.4.0</version>
</dependency>
             </dependencies>

<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>


SecondLevelCachaeHibernate5Application .java

package in.jk.hibernate5.second.level.cache;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import in.jk.hibernate5.HibernateUtils;

public class SecondLevelCachaeHibernate5Application {

private static SessionFactory sessionFactory;

public static void main(String[] args) {

sessionFactory = HibernateUtils.buildSessionFactory();
SecondLevelCachaeHibernate5Application.addEmployee();
SecondLevelCachaeHibernate5Application.findEmployeeByCache();
SecondLevelCachaeHibernate5Application.findEmployeeByQueryCache();

}

private static void addEmployee() {
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();

Employee employee = new Employee();
employee.setEmpId(1);
employee.setName("J K");
employee.setCompany("Google");
//session.persist(employee);

transaction.commit();

session.close();

System.out.println("Employee Added ....");
}

private static void findEmployeeByCache() {
System.out.println("Hibernate Cache  :: ");

Session session = sessionFactory.openSession();

Transaction transaction1 = session.beginTransaction();

Employee emp = session.get(Employee.class, 1);

System.out.println("Employee :: 1 " + emp);

System.out.println("-------------------------------------------------");

Employee emp2 = session.get(Employee.class, 1);

System.out.println("Employee :: 2  " + emp2);

transaction1.commit();
session.close();
System.out.println("..............Session Close .........");
System.out.println();
Session session2 = sessionFactory.openSession();

Transaction transaction2 = session2.beginTransaction();

Employee emp3 = session2.get(Employee.class, 1);

System.out.println("Employee :: 3 " + emp3);

System.out.println("-------------------------------------------------");

Employee emp4 = session2.get(Employee.class, 1);

System.out.println("Employee :: 4  " + emp4);

transaction2.commit();
session2.close();
}
private static void findEmployeeByQueryCache() {
System.out.println("Hibernate Query Cache  :: ");


Session session = sessionFactory.openSession();

Transaction transaction1 = session.beginTransaction();

Query<Employee> query = session.createQuery("FROM Employee" ,Employee.class); 
query.setCacheable(Boolean.TRUE);
List<Employee> employees =query.getResultList();
employees.forEach(System.out::println);


System.out.println("-------------------------------------------------");

Query<Employee> query2 = session.createQuery("FROM Employee" ,Employee.class); 
query2.setCacheable(Boolean.TRUE);
List<Employee> employees2 =query2.getResultList();
employees2.forEach(System.out::println);
transaction1.commit();

session.close();

System.out.println("..............Session Close .........");
System.out.println();

Session session2 = sessionFactory.openSession();

Transaction transaction2 = session2.beginTransaction();

Query<Employee> query3 = session2.createQuery("FROM Employee" ,Employee.class); 
query3.setCacheable(Boolean.TRUE);
List<Employee> employees3 =query3.getResultList();
employees3.forEach(System.out::println);

System.out.println("-------------------------------------------------");

Query<Employee> query4 = session2.createQuery("FROM Employee" ,Employee.class); 
query4.setCacheable(Boolean.TRUE);
List<Employee> employees4 =query4.getResultList();
employees4.forEach(System.out::println);

transaction2.commit();

session2.close();

}

}



Ouput in Console  here ::
SQL Query execute only once  out of four call in rest case object return from cache even if we close the session .


Employee Added Succussfully ....
Fetching Object by Hibernate Cache  :: 
Hibernate: select employee0_.emp_id as emp_id1_26_0_, employee0_.company as company2_26_0_, employee0_.name as name3_26_0_ from hibernate5_second_level_cache_employee employee0_ where employee0_.emp_id=?
Employee :: 1 Employee [empId=1, name=J K, company=Google]
-------------------------------------------------
Employee :: 2  Employee [empId=1, name=J K, company=Google]
----------- Session Close ---------------

Here No SQL Query to Database Object return form Cache .
Employee :: 3  Employee [empId=1, name=J K, company=Google]
-------------------------------------------------
Employee :: 4  Employee [empId=1, name=J K, company=Google]
Hibernate Query Cache  :: 
Hibernate: select employee0_.emp_id as emp_id1_26_, employee0_.company as company2_26_, employee0_.name as name3_26_ from hibernate5_second_level_cache_employee employee0_
Employee [empId=1, name=J K, company=Google]
-------------------------------------------------
Employee [empId=1, name=J K, company=Google]
----------- Session Close ---------

Here No SQL Query to Database Object return form Cache .
Employee [empId=1, name=J K, company=Google]
-------------------------------------------------
Employee [empId=1, name=J K, company=Google]





No comments:

Post a Comment