20.4. 查询缓存(The Query Cache)
查询的结果集也可以被缓存。只有当经常使用同样的参数进行查询时,这才会有些用处。
20.4.1. 启用查询缓存
按 照应用程序的事务性处理过程,查询结果的缓存将产生一些负荷。例如,如果缓存针对 Person 的查询结果,在 Person 发生了修改时,Hibernate 将需要跟踪这些结果什么时候失效。因为大多数应用程序不会从缓存查询结果中受益,所以 Hibernate 在缺省情况下将禁用缓存。要使用查询缓存,你首先需要启用查询缓存:
hibernate.cache.use_query_cache true
这个设置创建了两个新的缓存 region:
org.hibernate.cache.StandardQueryCache
,保存缓存的查询结果org.hibernate.cache.UpdateTimestampsCache
,保存对可查询表的最近更新的时间戳。它们用于检验查询结果。
重要
If you configure your underlying cache implementation to use expiry or timeouts is very important that the cache timeout of the underlying cache region for the UpdateTimestampsCache be set to a higher value than the timeouts of any of the query caches. In fact, we recommend that the the UpdateTimestampsCache region not be configured for expiry at all. Note, in particular, that an LRU cache expiry policy is never appropriate.
如上面所提及的,绝大多数的查询并不能从查询缓存中受益,所以 Hibernate 默认是不进行查询缓存的。如若需要进行缓存,请调用
org.hibernate.Query.setCacheable(true)
方法。这个调用会让查询在执行过程中时先从缓存中查找结果,并将自己的结果集放到缓存中去。
注意
查询缓存不会缓存缓存中实际实体的状态;它只缓存标识符值和值类型的结果。出于这个原因,对于那些作为查询结果缓存的一部分(和集合缓存一样)进行缓存的实体,查询缓存应该和二级缓存一起使用。
20.4.2. 查询缓存区
如果你要对查询缓存的失效政策进行精确的控制,你必须调用
Query.setCacheRegion()
方法,为每个查询指定其命名的缓存区域。
List blogs = sess.createQuery("from Blog blog where blog.blogger = :blogger")
.setEntity("blogger", blogger)
.setMaxResults(15)
.setCacheable(true)
.setCacheRegion("frontpages")
.list();
如果查询需要强行刷新其查询缓存区域,那么你应该调用
org.hibernate.Query.setCacheMode(CacheMode.REFRESH)
方法。 这对在其他进程中修改底层数据(例如,不通过Hibernate修改数据),或对那些需要选择性更新特定查询结果集的情况特别有用。这是对 org.hibernate.SessionFactory.evictQueries()
的更为有效的替代方案,同样可以清除查询缓存区域。