以下配置基于spring boot版本1.4.2.RELEASE,默认引入的hibernate版本为5.0.11.Final,ehcache版本2.10.3。
Ehcache作为Hibernate的二级缓存的实现。
1.application.properties中,添加:
#打开hibernate统计信息
spring.jpa.properties.hibernate.generate_statistics = true
#打开二级缓存
spring.jpa.properties.hibernate.cache.use_second_level_cache = true
#打开查询缓存
spring.jpa.properties.hibernate.cache.use_query_cache = true
#指定缓存provider
spring.jpa.properties.hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
#配置shared-cache-mode
spring.jpa.properties.javax.persistence.sharedCache.mode = ENABLE_SELECTIVE
2.接口从JpaSpecificationExecutor继承
根据具体Entity类型,重写JpaSpecificationExecutor中的方法,并且加上@QueryHints注解
// 不涉及分页的查询
@QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") }) // 使用查询缓存
List<UserAddress> findAll(Specification<UserAddress> spec, Sort sort);
// 分页查询
@QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") }) // 使用查询缓存
Page<UserAddress> findAll(Specification<UserAddress> spec, Pageable pageable);
3.总结
通过上述配置,在不涉及到分页查询的情况下,确实实现了查询缓存。
通过缓存事件监听,查询结果确实放入了查询缓存中。
在第二次查询的情况下,不会发出查询sql。
而对于分页查询来说,每次分页查询会发出两条查询sql。
第一条为:select count(xxx.id) from ..........;
第二条为:select xxx, xxx,....from ....;
通过缓存事件监听,select count的查询结果并未被放入查询缓存;而select的查询结果确实被放入了查询缓存中。
所以在第二次分页查询的情况下,仍然会发出一条select count语句;而select的sql确实没有发出。
4.疑问
虽说对于不涉及分页的查询,能够实现查询缓存;对于涉及分页的查询,部分实现了查询缓存。
但总觉得这种方式不够优雅,不知道同学们有没有更好的解决方案。