1.MyBatis一级缓存
Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对
于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对
象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会
将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,
SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
2.MyBatis二级缓存
MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能
3.开启二级缓存
SqlSessionFactory层面上的二级缓存默认是不开启的,二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置就可以开启缓存了
4. Mybatis开启使用二级缓存
修改配置文件mybatis-config.xml加入
<setting name="cacheEnabled"value="true"/>
在mapper.xml中开启二缓存,mapper.xml下的sql执行完成会存储到它的缓存区
<!--回收策略为先进先出,每隔60秒刷新一次,最多缓存512个引用对象,只读-->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
参数说明:
eviction:
LRU 最近最少使用的:移除最长时间不被使用的对象
FIFO 先进先出:按对象进入缓存的顺序来移除它们
SOFT 软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
flushInterval :刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默
认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新(mia毫秒单位)
size :引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。
默认值是1024
readOnly :(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实
例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列
化)。这会慢一些,但是安全,因此默认是false
5.select,insert,update标签中的缓存属性
useCache=false,禁用二级缓存
flushCache=true 刷新缓存 ,一般用于insert,update(目前版本可以自动刷新)
6.SpringBoot开启MyBatis缓存+ehcache
引入缓存的依赖包,在配置 pom.xml 文件中添加
<!--添加缓存-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
添加缓存的配置文件 ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下
user.home : 用户主目录
user.dir : 用户当前工作目录
java.io.tmpdir : 默认临时文件路径
-->
<diskStore path="java.io.tmpdir/Tmp_EhCache"/>
<!--
name: 缓存名称
eternal: true表示对象永不过期,此时会忽略
timeToIdleSeconds和timeToLiveSeconds属性,默认为false
timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对
象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过
期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表
示对象可以无限期地处于空闲状态
timeToLiveSeconds: 设定对象允许存在于缓存中的最长时间,以秒为单位。当对
象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过
期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表
示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
maxElementsInMemory: 内存中最大缓存对象数;maxElementsInMemory界限
后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了
Serializable接口才行
memoryStoreEvictionPolicy: 当达到maxElementsInMemory限制时,Ehcache将会根
据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少
访问次数)
maxElementsOnDisk: 硬盘中最大缓存对象数,若是0表示无穷大
overflowToDisk: 是否保存到磁盘,当系统宕机时
diskPersistent: 是否缓存虚拟机重启期数据,是否持久化磁盘缓存,当这个
属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为index的文件,这个文件
中存放了已经持久化在磁盘中的cache的index,找到后会把cache加载到内存,要想把cache真正持久化到
磁盘,写程序时注意执行net.sf.ehcache.Cache.put(Element element)后要调用flush()方法
diskSpoolBufferSizeMB: 这个参数设置DiskStore(磁盘缓存)的缓存区大小。默
认是30MB。每个Cache都应该有自己的一个缓冲区
diskExpiryThreadIntervalSeconds: 磁盘失效线程运行时间间隔,默认为120秒
clearOnFlush: 内存数量最大时是否清除
-->
<!--defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则默认缓存策略-->
<defaultCache eternal="false" maxElementsInMemory="1000"
overflowToDisk="true" diskPersistent="true" timeToIdleSeconds="0"
timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
<cache
name="myCache"
eternal="false"
maxElementsInMemory="200"
overflowToDisk="false"
diskPersistent="true"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
设置项目启动时使用缓存
@SpringBootApplication
@ComponentScan(basePackages = {"com.hz.service","com.hz.controller"})
@MapperScan("com.hz.dao")
@EnableCaching //开启缓存
public class Springboot1Application {
public static void main(String[] args) {
SpringApplication.run(Springboot1Application.class, args);
}
}
在application.properties配置中读取ehcache.xml文件
#读取缓存配置文件
spring.cache.ehcache.config=classpath:ehcache.xml
#最后记得开启打印sql语句,方便测试
logging.level.com.hz.dao=debug
7.Spring Cache注解使用
@Cacheable
可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当
标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被
调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,
而不需要再次执行该方法。
@Cacheable可以指定三个属性,value、key和condition
@Cacheable("myCache1")//Cache是发生在ehcache.xml中myCache1上的
public User find(Integer id) {
....
}
@Cacheable({"cache1", "cache2"})//Cache是发生在ehcache.xml中cache1和cache2上的
public User find(Integer id) {
.....
}
//自定义策略是指我们可以通过Spring的EL表达式来指定我们的key
//#id指参数id作为key
@Cacheable(value="myCache1", key="#id")
public User find(Integer id) {
...
}
//#p0标识第一个参数作为key
@Cacheable(value="myCache1", key="#p0")
public User find(Integer id) {
.....
}
//#user.user_id表示对象user属性user_id作为key
@Cacheable(value="myCache1", key="#user.user_id")
public User find(User user) {
.....
}
@Cacheable(value="myCache1", key="#p0.user_id")
public User find(User user) {
.....
}
Spring还为我们提供了一个root对象可以用来生成key
//表示只有当user的id为偶数时才会进行缓存
@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
public User find(User user) {
...
}
@CachePut
使用@CachePut时我们可以指定的属性跟@Cacheable是一样的
@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行
过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中
@CacheEvict 清除缓存
可以指定的属性有value、key、condition、allEntries、beforeInvocation
@CacheEvict(value="myCache",key="#p0.user_id")
public int updUser(SfUser user) throws Exception {
return sfUserMapper.updUser(user);
}
allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了
allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元
素,这比一个一个清除元素更有效率
@CacheEvict(value="users", allEntries=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}