Mybatis的一级缓存和二级缓存
一级缓存
基于perpetualcache的hashmap本地缓存,其作用域默认是一个SqlSession,当session进行flush或者close之后,将该session中的cache进行清空。
一级缓存是默认开启的:缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。
另外的,对于service中的sqlsession,每次查询之后会关闭,数据也随之清空(如果不是在同一个事务中每个Mapper的每次查询操作都对应一个全新的SqlSession实例),所以使用一级缓存需要开启事务。
更改一级缓存的范围,可以在Mybatis的配置文件中,通过localCacheScope指定,建议不修改。
<setting name="localCacheScope" value="STATEMENT"/>
二级缓存
机制与一级缓存类似,默认采用perpetualcache,hashmap存储,不同在于存储作用域为Mapper(namespace),并且可以自定义存储。
对于存储数据更新机制,当某一个作用域进行了C/U/D之后,默认该作用域下所有select中的缓存将被clear。
二级缓存是需要手动开启的:
- 在Mybatis配置文件中,开启二级缓存
<setting name="cacheEnabled" value="true"/>
- 配置XXXDao.xml支持二级缓存
<cache/>
- 配置查询的方法支持二级缓存
<select id="findById" resultType="com.example.domain.User" parameterType="INT" useCache="true">
SELECT * FROM USER WHERE ID = #{ID}
</select>
禁用缓存:
在映射文件中:
默认值是true useCache=“false”
<select id="findAllPets" resultMap="petsMap" useCache="false">
select * from pets
</select>
刷新缓存:
在映射文件中:
属性:flushCache=“true”
刷新缓存,在查询语句中,默认值是false,在新增删除修改语句中,默认值是true(清空缓存)
一级缓存和二级缓存区别
mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。
二级缓存是SqlSessionFactory级别的缓存,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储的是数据,当命中二级缓存时,通过存储的数据构造对象返回。
查询数据的时候,查询的流程是二级缓存 > 一级缓存 > 数据库。
开启情况 | 作用域 | 缓存内容 | |
---|---|---|---|
一级缓存 | 默认开启 | sqlSession | 对象 |
二级缓存 | 手动开启 | Mapper | 数据 |
二级缓存使用原则
- 只能在一个命名空间下使用二级缓存
由于二级缓存中的数据是基于namespace的,即不同namespace中的数据互不干扰。在多个namespace中若均存在对同一个表的操作,那么这多个namespace中的数据可能就会出现不一致现象。 - 在单表上使用二级缓存
如果一个表与其它表有关联关系,那么就非常有可能存在多个namespace对同一数据的操作。而不同namespace中的数据互补干扰,所以就有可能出现多个namespace中的数据不一致现象。 - 查询多于修改时使用二级缓存
在查询操作远远多于增删改操作的情况下可以使用二级缓存。因为任何增删改操作都将刷新二级缓存,对二级缓存的频繁刷新将降低系统性能。