0
Sponsored Links


Ad by Google
I have already posted about Hibernate First Level Cache and How second level cache works in Hibernate here. And now, In this post I am going to show you about how to use Query Cache in Hibernate. Hibernate Query Cache is used with Second level cache, before going to the code, let me list you few points about Query Cache and then we will dive into the coding, of course at last, I'll share you the link to download the complete example of Query Cache. Hibernate is very powerful ORM framework and it's Criteria Query and Hibernate Fetching strategies always very useful.
How Query Cache Works :
The Query Cache does not cached the entities unlike Second Level Cache, It cached the queries and the return identifiers of the entities. Once it cached the identifiers than, It took help from Hibernate Second level cache to load the entities based on the identifiers value. So Query cache always used with Second level cache to get better result, because only query cache will cached the identifiers not the complete entities.

How to enable Query Cache in Hibernate :
Add this property in hibernate configuration file
<property name="hibernate.cache.use_query_cache">true</property>
Set query cacheable true with below syntax,
query.setCacheable(true);
OK, Now lets implement the complete example of Query Cache. In this tutorial, I am using country table and below is the structure of country table.

Table - Country
CREATE DATABASE ;

USE `hibernate_tutorial`;

/*Table structure for table `country` */

DROP TABLE IF EXISTS `country`;

CREATE TABLE `country` (
  `country_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `country_code` varchar(255) DEFAULT NULL,
  `country_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`country_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
Create Country.java annotated class
If required you can follow Step-by-Step-Hibernate-Tutorial in eclipse from here
Country.java
package com.javamakeuse.poc.pojo;

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 org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "country")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "country")
public class Country {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 @Column(name = "country_id")
 private long countryID;

 @Column(name = "country_name")
 private String countryName;

 @Column(name = "country_code")
 private String countryCode;

 public Country() {
 }

 public Country(String countryName, String countryCode) {
  super();
  this.countryName = countryName;
  this.countryCode = countryCode;
 }

 public String getCountryName() {
  return countryName;
 }

 public String getCountryCode() {
  return countryCode;
 }

 @Override
 public String toString() {
  return "Country [countryID=" + countryID + ", countryName="
    + countryName + ", countryCode=" + countryCode + "]";
 }

}

HibernateUtility.java class to build SessionFactory
package com.javamakeuse.poc.util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtility {
 private static final SessionFactory sessionFactory = buildSessionFactory();

 private static SessionFactory buildSessionFactory() {
  Configuration configuration = new Configuration();
  configuration.configure();

  ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
    .applySettings(configuration.getProperties()).build();
  SessionFactory sessionFactory = configuration
    .buildSessionFactory(serviceRegistry);
  return sessionFactory;
 }

 public static SessionFactory getSessionFactory() {
  return sessionFactory;
 }
}
I am using second level cache with query cache in this tutorial, so we have to configured second level cache also and for the same lets create ehcache.xml file, to understand second level cache please see how second level cache work in Hibernate
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>

 <diskStore path="F:/tmp" />

 <defaultCache maxEntriesLocalHeap="4000" eternal="false"
  timeToIdleSeconds="60" timeToLiveSeconds="120" diskSpoolBufferSizeMB="20"
  maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120"
  memoryStoreEvictionPolicy="LRU" statistics="true">
  <persistence strategy="localTempSwap" />
 </defaultCache>

 <cache name="country" maxEntriesLocalHeap="4000" eternal="false"
  timeToIdleSeconds="5" timeToLiveSeconds="10">
  <persistence strategy="localTempSwap" />
 </cache>

 <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
  maxEntriesLocalHeap="5000" eternal="true">
  <persistence strategy="localTempSwap" />
 </cache>
</ehcache>
Create hibernate.cfg.xml file
Enable both second level cache as well as query cache in 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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernate_tutorial</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
         
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        
         <!-- Enable Second Level Cache -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="net.sf.ehcache.configurationResourceName">ehcache.xml</property>
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
        <property name="hibernate.cache.use_query_cache">true</property>
 
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="hbm2ddl.auto">update</property>
        <mapping class="com.javamakeuse.poc.pojo.Country"/>
          
    </session-factory>
</hibernate-configuration>

Now create Main.java class to test query cache example.
package com.javamakeuse.poc.service;

import org.hibernate.Query;
import org.hibernate.Session;

import com.javamakeuse.poc.pojo.Country;
import com.javamakeuse.poc.util.HibernateUtility;

public class Main {
 public static void main(String[] args) {
  System.out.println(getCountry(1));
  System.out
    .println("Going to fetch Country from Query Cache*************");
  System.out.println(getCountry(1));
 }

 public static Country getCountry(long id) {

  Session session = HibernateUtility.getSessionFactory().openSession();

  Query query = session
    .createQuery("from Country c where c.countryID = :countryId ");
  query.setParameter("countryId", id);
  query.setMaxResults(1);
  query.setCacheable(true);
  return query.list() == null ? null : (Country) query.list().get(0);

 }
}

Run it, although we are calling getCountry(1) methods twice in main method, but it will generate only one sql query and next time it will fetched the records from the query cached and second level cache.

OUT PUT:
Hibernate: 
    select
        country0_.country_id as country_1_0_,
        country0_.country_code as country_2_0_,
        country0_.country_name as country_3_0_ 
    from
        country country0_ 
    where
        country0_.country_id=? limit ?
Country [countryID=1, countryName=Australiya, countryCode=+61]
Going to fetch Country from Query Cache*************
Country [countryID=1, countryName=Australiya, countryCode=+61]

Now just disabled the second level cache and see the differences, below is the syntax to disabled the second level cache in hibernate.cfg.xml
<property name="hibernate.cache.use_second_level_cache">false</property>
After disabling second level cache,it will generate two sql query.
OUT PUT:
Hibernate: 
    select
        country0_.country_id as country_1_0_,
        country0_.country_code as country_2_0_,
        country0_.country_name as country_3_0_ 
    from
        country country0_ 
    where
        country0_.country_id=? limit ?
Country [countryID=1, countryName=Australiya, countryCode=+61]
Going to fetch Country from Query Cache*************
Hibernate: 
    select
        country0_.country_id as country_1_0_0_,
        country0_.country_code as country_2_0_0_,
        country0_.country_name as country_3_0_0_ 
    from
        country country0_ 
    where
        country0_.country_id=?
Country [countryID=1, countryName=Australiya, countryCode=+61]

Now disabled query cache by setting false as
query.setCacheable(false);
and it will generate four sql query.
OUT PUT:
Hibernate: 
    select
        country0_.country_id as country_1_0_,
        country0_.country_code as country_2_0_,
        country0_.country_name as country_3_0_ 
    from
        country country0_ 
    where
        country0_.country_id=? limit ?
Hibernate: 
    select
        country0_.country_id as country_1_0_,
        country0_.country_code as country_2_0_,
        country0_.country_name as country_3_0_ 
    from
        country country0_ 
    where
        country0_.country_id=? limit ?
Country [countryID=1, countryName=Australiya, countryCode=+61]
Going to fetch Country from Query Cache*************
Hibernate: 
    select
        country0_.country_id as country_1_0_,
        country0_.country_code as country_2_0_,
        country0_.country_name as country_3_0_ 
    from
        country country0_ 
    where
        country0_.country_id=? limit ?
Hibernate: 
    select
        country0_.country_id as country_1_0_,
        country0_.country_code as country_2_0_,
        country0_.country_name as country_3_0_ 
    from
        country country0_ 
    where
        country0_.country_id=? limit ?
Country [countryID=1, countryName=Australiya, countryCode=+61]

That's it :)

Download the complete source from here

Sponsored Links

0 comments:

Post a Comment