Hibernate Query Cache Example shows you how Query Cache works with Second level cache. Hibernate Query Cache is used with Second level cache but it does not cached the entities unlike Second Level Cache. Query Cache is caching the combination of query and values provided as parameters as key, and list of identifiers of objects returned by query execution as values. Notice that Hibernate will load objects using cached identifiers from second level cache.
Other interesting posts you may like
Let’s begin:
How to enable Query Cache in Hibernate
Add this property in hibernate configuration file
1 |
<property name="hibernate.cache.use_query_cache">true</property> |
Then set query cacheable true with below syntax,
1 |
query.setCacheable(true); |
Create project directory structure
In this Hibernate Query Cache Example, we are creating a maven project in the Eclipse, final project directory structure will look like below image
Hibernate Configuration file
Query cache is enabled in hibernate configuration file. However Query cache always used with Second level cache, we must enable Second level cache too. If you don’t know about Second level cache yet, please the tutorial Hibernate Second Level Cache Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration SYSTEM "classpath://org/hibernate/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.username">javabycode</property> <property name="hibernate.connection.password">mypassword</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/javabycode</property> <property name="format_sql">false</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!-- For singleton factory --> <!-- <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property> --> <!-- enable second level cache and query cache --> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.use_query_cache">true</property> <property name="net.sf.ehcache.configurationResourceName">/myehcache.xml</property> <mapping class="com.javabycode.hibernate.model.Student" /> </session-factory> </hibernate-configuration> |
In this example, we are using EHCache for second level cache. This configuration makes sure that EHCache works normally.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <diskStore path="java.io.tmpdir/ehcache" /> <defaultCache maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30" maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" statistics="true"> <persistence strategy="localTempSwap" /> </defaultCache> <cache name="employee" maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="5" timeToLiveSeconds="10"> <persistence strategy="localTempSwap" /> </cache> <cache name="org.hibernate.cache.internal.StandardQueryCache" maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120"> <persistence strategy="localTempSwap" /> </cache> <cache name="org.hibernate.cache.spi.UpdateTimestampsCache" maxEntriesLocalHeap="5000" eternal="true"> <persistence strategy="localTempSwap" /> </cache> </ehcache> |
Now create a program to test Hibernate query cache example
As you see above, we need to enable query cache in java program by setting cacheable true like this below main class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package com.javabycode.hibernate; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import com.javabycode.hibernate.model.Student; public class HibernateQueryCacheExample { public static void main(String[] args) { SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); String sql = "from Student s where s.id=:studentId"; Query query = session.createQuery(sql); query.setParameter("studentId", 33L); query.setCacheable(false);// set default is false Student student = (Student) query.list().get(0); System.out.println("Student: "+student); //Enable query cache System.out.println("----Fetch Student from Query Cache----"); Query query2 = session.createQuery(sql); query2.setParameter("studentId", 33L); query2.setCacheable(true); System.out.println("----Query cache is enabled and store query result----"); Student student2 = (Student) query2.list().get(0); System.out.println("Student: "+student2); System.out.println("----Fetch Student from Query Cache again----"); Query query3 = session.createQuery(sql); query3.setParameter("studentId", 33L); query3.setCacheable(true); Student student3 = (Student) query3.list().get(0); System.out.println("Student: "+student3); } } |
Run above main and output is printed like below:
1 2 3 4 5 6 7 8 9 10 11 |
----Step 1---- Hibernate: select student0_.id as id1_0_, student0_.CODE as CODE2_0_, student0_.ENTERING_DATE as ENTERING3_0_, student0_.NAME as NAME4_0_, student0_.NATIONALITY as NATIONAL5_0_ from STUDENT student0_ where student0_.id=? Student: Student [id=33, name=David Villa, enteringDate=2016-10-17 16:01:22.0, nationality=USA, code=1234569] ----Step 2---- ----Fetch Student from Query Cache---- ----Query cache is enabled and store query result---- Hibernate: select student0_.id as id1_0_, student0_.CODE as CODE2_0_, student0_.ENTERING_DATE as ENTERING3_0_, student0_.NAME as NAME4_0_, student0_.NATIONALITY as NATIONAL5_0_ from STUDENT student0_ where student0_.id=? Student: Student [id=33, name=David Villa, enteringDate=2016-10-17 16:01:22.0, nationality=USA, code=1234569] ----Step 3---- ----Fetch Student from Query Cache again---- Student: Student [id=33, name=David Villa, enteringDate=2016-10-17 16:01:22.0, nationality=USA, code=1234569] |
Let’s look at the output:
Step 1: Query cache is set false, by default. We load student object by query and query log is fired.
Step 2: Query cache is set true. Then we load student object by query again. As you see that query log is still fired here. It means that the student object is not stored yet in query cache before (step 1). Actually, the student object is just stored in this step 2.
Step 3: Query cache is set true. One more, we load student object by query and query log doesn’t appear. It means that student object is load from query cache.
That’s it on the Hibernate Query Cache Example.