缓存可分为一级缓存和二级缓存
一级缓存:sqlSession级别的缓存,默认打开并且不可关闭
二级缓存:Mapper级别的缓存,默认关闭需要手动打开
一级缓存(Local Cache)
一级缓存是sqlSession级别的,也就是说一级缓存与sqlSession关联,只有同一个sqlSession才可能访问相同的缓存资源。
所谓的缓存资源,就是在执行查询语句时把 查询语句 与 结果集 成对缓存(相当于Map的key与value对应)
当执行DML语句(delete,insert,update)时,一级缓存资源全部清空(很明显,这个机制是为了避免查询到脏数据)
除了执行DML语句会清空缓存,还可以手动执行SQLSession的clearCache方法来清空一级缓存。
需要注意的是,永远不要对查询出来的结果进行修改,因为这样的修改会同步到缓存数据中,那么缓存数据就被污染。
一级缓存默认是与SQLSession相关联,但是也可以设置为与statement相关联,这样只有用同一个statement执行查询语句才能共享同一个一级缓存资源,设置方法:在mybatis-config.xml文件中
<settings>
<setting name="localCacheScope" value="STATEMENT"/>
</settings>
二级缓存
二级缓存是Mapper级别的,也就是说与Mapper组件(准确来讲是同名空间)相关联。
与一级缓存一样,DML语句也会清空二级缓存
在Mapper.xml中定义cache元素来开启次Mapper组件的二级缓存:
<cache/>
当然也可以为cache指定一些属性,不过一般用默认属性就够了
eviction:缓存的清空算法(有LRU,FIFO,SOFT,WEAK四种,具体在此不展开)
flushInterval:指定缓存刷新时间间隔,默认永不刷新
type:(注解中用implementation属性):缓存实现类,极少用到
readyOnly(注解中用readWrite):指定该缓存是否只读,默认为false
size:最多缓存的项数
如果需要两个Mapper共享一个二级缓存,则只需在Map.xml中定义cache-ref元素,并且指定要关联的Mapper的namespace
<cache-ref namespace="另一个Mapper的namespace"/>
关联查询时应该把他们的二级缓存也关联起来(如果用到二级缓存的话),防止获取脏数据。
当然也可通过注解的方式来开启二级缓存 ,核心注解有:
@CacheNamespace和@CacheNamespaceRef
其他需要说明的是:
二级缓存并不保存在内存中,可能保存在磁盘或者数据库中,所以对应的类需要序列化,实现Serialization接口。
只有当SQLSession commit或者close时才会把数据写入二级缓存。