Understanding Caching in Hibernate – Part Two : The Query Cache
In the last post I wrote on caching in Hibernate in general as well as on the behavior of the session cache. In this post we will have a closer look at the QueryCache. I will not explain the query cache in details as there are very good articles like Hibernate: Truly Understanding the Second-Level and Query Caches.
As we have seen in the last post the session cache can help in caching values when we have an _EntityKey_ available. If we do not have the key, we ran into the problems of having to issue multiple queries for retrieving the same object. This was the reason why the session cache worked fine for the _load_ method but not when we used _session.createQuery()_.
Now this is the point where the query cache comes into play. The query cache is responsible for caching the results of queries – or to be more precise the keys of the objects returned by queries. Let us have a look how Hibernate uses the query cache to retrieve objects. In order to make use of the query cache we have to modify the person loading example as follows.
Session session = getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Person p where p.id=1");
query.setCacheable(true);
Iterator it = query.list().iterator();
while (it.hasNext ()){
Person p = (Person) it.next();
System.out.println(p.getFirstName());
}
query = session.createQuery("from Person p where p.id=1");
query.setCacheable(true);
it = query.list().iterator();
while (it.hasNext ()){
Person p = (Person) it.next();
System.out.println(p.getFirstName());
}
tx.commit();
session.close();
As highlighted in bold face we had to add a line for defining that the query is actually cachable. If we would not do this, it won’t be cached. (Note: The while loops could be omitted here. I am using for other examples where we have multiple results. …. just for code esthetics lovers). Additionally we also have to change the hibernate configuration to enable the query cache. This is done by adding the following line to the Hibernate configuration.
<property name="hibernate.cache.use_query_cache">true</property>
Unlike most examples I found on the web I will not immediately enable the second-level cache. As the basic working do not depend on it and I do not want to create the impression that the query cache requires the second level or vice versa. Let us now verify that everything is working correctly. As we can see below only the first _query.list()_ result in a SQL statement to be issued.
The question now is, what happens internally. Therefore we analyze what happens within the second _get_ method of the _StandardQueryCache_. As we can see in the image below Hibernate first tries to retrieve the key values from the cache (as we can see the query cache internally uses the _EhCache_). After retrieving the keys the person entity is loaded from the session cache.
Query Cache Pitfalls
The query cache can be really usefull to optimize the performance of your data access layer. However there are a number of pitfalls as well. This blog post describes a serious problem regarding memory consumption of the Hibernate query cache when using objects as parameters.
Conclusion
We have learned that the query cache helps us to cache the keys of results of Hibernate queries. These keys are then used to retrieve data objects using the Hibernate Internal loading behavior which involves the session cache and potentially also the second-level cache.







Hi,
I am using hibernate entity manager.
I wanted to use the query cache as you explained above, but Query returned by entity manager createQuery() method does not support setCacheable() ability.
Interessante Informationen.
Gute Arbeit hier! Gute Inhalte.
[...] the last posts I already covered the session cache as well as the query cache. In this post I will focus on the second-level cache. The Hibernate Documentation provides a good [...]
@Michael, what you can do is on the query you create, you can say:
entityManager.createQuery(“select person from person”).setHint(“org.hibernate.cacheable”, true).getResultList();
Then it will enable the query caching.
Hope this helps.
The point is that the Entity Manager is part of JPA and JPA does not define those nice caching methods. However as Shervin wrote you can use the hints methods to pass this on to hibernate.
Caching is a bit of a neglected part of JPA – also of JPA 2.0 as it seems right now.
[...] Part 2 – http://blog.dynatrace.com/2009/02/16/understanding-caching-in-hibernate-part-two-the-query-cache/ [...]
Great post thank you. But I have a question; I can’t remove the cached query from the cache! I need to refresh the cache after performing data changes.
When object actually gets into second level cache ?
@Sami You can say explicitly that you do not want a query to be cached. However if you expect your data to change regularly query caching might not be the best ideal
@Jigar. Objects get into the second level cache if you have defined that they should be cached. You can do this either by annotations or in a Hibernate config file.
[...] Reads: Understanding Hibernate Session Cache, Understanding the Query Cache, Understanding the Second Level [...]
Hi sir,
How would you caching of a particular named query?
Sorry a mistake in the above post.
How would you remove the caching of a particular named query?
Thanks a lot for your clear explanation but where can i see this figure parts..How to see what has got executed?(blue highlighted parts I mean)
@Bavani
You have to explictly specify that a query gets cached so it will not be cached by default. Is this what you meant?
@Hema
The traces show what has been executed. You can see this for your code by using tracing solutions like dynaTrace.
[...] Queries, however, are not cached by default. If you want to know more read this article on the Hibernate Query Cache. public void doubleLoad (){ EntityManager em = factory.createEntityManager(); [...]
[...] http://blog.dynatrace.com/2009/02/16/understanding-caching-in-hibernate-part-two-the-query-cache/ [...]
@Alois tnx for the tip: use of dynaTrace.
but, I couldn’t even silence myself for what I notice about your contraditory (paradoxal) statements: “…enable the second-level cache. As the basic working do not depend on it and I do not want to create the impression that the query cache requires the second level or vice versa.” and “as we can see the query cache internally uses the _EhCache_”.
For instance, is there the dependence ehcache.jar and is it referenced in your ExampleApp config??!
Finally, QueryCache really demands (or not) a 2ºlevel Cache Provider??!
Derlon
@Alois tnx for the tip: use of dynaTrace.
But, I couldn’t even silence myself for what I notice about your contraditory (paradoxal) statements: “…enable the second-level cache. As the basic working do not depend on it and I do not want to create the impression that the query cache requires the second level or vice versa.” and “as we can see the query cache internally uses the _EhCache_”.
For instance, is there the dependence ehcache.jar and is it referenced in your ExampleApp config??!
Finally, QueryCache really demands (or not) a 2ºlevel Cache Provider??!
Derlon
Derlon,
I state that you can use the query cache also without the second level cache. In many cases you will want to however use both, but you do not need to.
EhCache is just one implementation of a cache provider to be used with Hibernate. In Hibernate – as I stated- EhCache is also used for the query cache. This however does not mean you use the second level. This depends on whether you set your Hibernate properties to enable the cache
[...] Reads: Understanding Hibernate Session Cache, Understanding the Query Cache, Understanding the Second Level [...]
[...] the last posts I already covered the session cache as well as the query cache. In this post I will focus on the second-level cache. The Hibernate Documentation provides a good [...]