Understanding Caching in Hibernate – Part Two : The Query Cache

来源:互联网 发布:2016淘宝京东市场份额 编辑:程序博客网 时间:2024/05/29 03:20

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 theQueryCache. I will not explain the query cache in details as there are very good articles likeHibernate: 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.

Caching by the Query Cache For Two Susequent Queries

Caching by the Query Cache For Two Susequent Queries

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.

Internal Behavior of the Hibernate Query Cache

Internal Behavior of the Hibernate Query 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.  Thisblog 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.

转自:http://apmblog.compuware.com/2009/02/16/understanding-caching-in-hibernate-part-two-the-query-cache/