在实际应用中,用于查询的数据量非常大,查询效率非常慢。为了提高查询效率,并减少对数据库的访问,一般都会使用二级缓存。二级缓存框架有很多,但hibernate默认使用的ehcache。ehcache是纯java进程的,缓存速度快,轻量级的框架。
1.首先在build.gradle中添加cache启动器依赖:
compile('org.springframework.boot:spring-boot-starter-cache')
2.在application.yml中添加以下配置:
spring:
jpa:
properties:
hibernate:
cache:
#使用二级缓存
use_second_level_cache: true
#查询使用缓存
use_query_cache: true
#缓存的工厂类
region.factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory
#查询打印sql,可验证二级缓存是否配置成功
show-sql: true
#配置ehcache的配置文件目录
cache:
ehcache:
config: classpath:ehcache.xml
3.配置ehcache.xml
<ehcache>
<diskStore path="user.dir/static"></diskStore>
配置默认缓存
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="person"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="18000"
timeToLiveSeconds="36000"
overflowToDisk="false"
/>
<!--
设定具体的命名缓存的数据过期策略
cache元素的属性:
name:缓存名称
maxEntriesLocalHeap:内存中最大缓存对象个数
maxElementsOnDisk:硬盘中最大缓存对象数,若是0表示无穷大
eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false
overflowToDisk:true表示当内存缓存的对象数目达到了maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行。
diskSpoolBufferSizeMB:磁盘缓存区大小,默认为30MB。每个Cache都应该有自己的一个缓存区。
diskPersistent:是否缓存虚拟机重启期数据
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认为120秒
timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地处于空闲状态
timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
-->
</ehcache>
3.entity中加注解:
@Cacheable() @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY,region = "person") @Entity public class Person{ }
4.repository加注解:
public interface PersonRepository extends JpaRepository{ @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true")}) public List<Person> findAll(); }
这样查询的时候,就会将结果缓存到内存里。查询方法上加QueryHint缓存才会生效。如果要对JPA接口提供(例如:JpaRepository 中的findOne)的方法使用缓存,可以在PersonRepository中覆盖父接口即可。