One of the common mistakes when using hibernate is to think: “no problem, hibernate handles the cache for me”. Wrong! By default hibernate does not cache anything. Well, as far as I understand it cache things in the session cache, but this is usually not relevant. First here is what cache refers to in hibernate:

  • session cache, enabled by default, but with a lifetime equals to the session
  • second-level cache, controlled by: hibernate.cache.use_second_level_cache, which stores objects by id
  • query-cache, controlled by: hibernate.cache.use_query_cache ,which stores query results

However, enabling these properties does not has any effect on the application usage of a cache.

Caching objects

In order to cache objects the magic combination requires to enable the second level cache and add a cache directive to the object in question mapping. For instance:

<pre class="programlisting"><class name="Currency">
    <span style="text-decoration: underline;"><cache usage="read-write"/></span>

Without the cache option this object would never be cached. Note that you have to choose the proper cache option considering the object usage and the type of cache used because not all caches support all cache usages.

Caching queries

In order to enable the cache for a query result you must enable the query cache and mark each query as cacheable:

Query query = session.createQuery("from c in class com... where c.active is true order by c.isocode");
<span style="text-decoration: underline;">query.setCacheable(true);</span>
query.list();

The most puzzling case is when you enable the query cache and see that your query is performing much poorly than previously. For example I had a query which performed in 1000ms for the first time and in 10000ms the second time after enabling the cache. Why, bump? The answer is that the query cache is a [query, params] -> [id1, …] cache. Which means only the id’s are cached so if the object itself is not cached. The process would be:

  • execute query
  • find id’s
  • because the objects are not cached load all objects corresponding to these id’s

So make sure that the objects which appear in the cached queries are also to be found in the second-level cache to have something like:

  • execute query
  • find id’s
  • load all objects with these id’s from the second level cache

Enabling the second level cache for the objects in question reduced the query time to 10ms the second time.