The information provided in this blog is validated against hibernate-core 3.6.7.Final and 3.5.6-Final.

Hibernate’s second level cache is used to cache domain objects and queries.
In this blog I want to focus on the query cache of hibernate and show how native queries affect the second level cache and how you can configure which caches are affected by a native query.

Background

Query caches are useful if you want to cache the result of a HQL or criteria query. But be careful if you are using query caches and native queries. Native queries can invalidate the second level caches. The reason is found in this class org.hibernate.engine.query.NativeSQLQueryPlan.


The org.hibernate.action.BulkOperationCleanupAction‘s constructor assumes that all tabel spaces are affected by the native query if the query doesn’t define affected spaces itself.


Hibernate must decide when it should invalidate a second level cache. Therefore it must know which sql statements that are sent to the database require a cache to be invalidated. If you let hibernate do all the sql stuff, it knows the statements it generates and therefore the tables that are affected. In this case hibernate can easily decide which caches have to be invalidated.

A native query can execute any sql you want, so only the creator of that query knows what the query does and which tabels are affected, if any.
Sometime you might only want to execute a native query to only change the connections properties, e.g. when using a oracle database.


But you can also execute a native query that affects the data of the domain objects.


Hibernate can’t know what you are doing and therefore it can’t know what caches need to be invalidated. As long as hibernate doesn’t know which caches are affected it must assume that all data is invalid to ensure data consistency. This means that hibernate will invalidate all caches.

Configure cache synchronization

Fortunatly the hibernate API let you specify the entities or query spaces that are affected by your query.
Tell hibernate which tables are affected by your query and hibernate will only invalidate caches that are based on that data.


The source 5 example demonstrates how to tell hibernate which entities are affected by a native query, but the hibernate api has more methods to define synchronization of caches.


Sometimes you want to execute a native query that doesn’t change any data like the query shown in source 3. Normally hibernate will invalidate all caches if you just execute such a query.  The reason why it does this is shown in source 1 and 2.
To prevent hibernate from invalidating the second level caches you can add an empty query space synchronization.


You can also add synchronization to the xml definition of a named sql query.