Mybatis对缓存提供支持,有三种缓存级别:一级缓存、二级缓存、自定义缓存。默认情况是开启一级缓存。
知识准备
Mybatis的基本构成:
- SqlSessionFactoryBuilder:构造器,通过配置文件或者代码生成SqlSessionFactory。
- SqlSessionFactory:工厂接口,依靠工厂来生成SqlSession。
- SqlSession:会话,既可以发送SQL去执行并返回结果,也可以获取Mapper的接口。
- SQL Mapper:由一个Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则,它负责发送SQL去执行,并返回结果。
Mybatis组件生命周期
- SqlSessionFactoryBuilder:利用XML或者Java编码获得资源来构建多个SqlSessionFactory。一旦构建完成SqlSessionFactory,就可以将其回收,生命周期只存在于方法的局部。
- SqlSessionFactory:作用是创建SqlSession,SqlSessionFactory的创建应该采用单例模式,防止连接资源的过多消耗,因此,SqlSessionFactory应该存在于Mybatis的整个生命周期。
- SqlSession:是一个会话,相当于JDBC的一个Connect对象。它的生命周期是请求数据库处理事务的过程中。是一个线程不安全的对象。
- SQL Mapper:一个接口,作用是发送SQL,然后返回结果,或者执行SQL从而修改数据库的数据。
一级缓存
一级缓存是SqlSession级别的缓存,为解决资源的浪费,Mybatis会在SqlSession对象中建立一个简单的缓存。Mybatis默认支持一级缓存,不需要在配置文件中进行配置。
底层实现
SqlSession将工作交给Executor执行器来完成,一级缓存实际上是使用PerpetualCache维护的,PerpetualCache的实现原理是HashMap。
工作流程
- 构建查询操作的key值,根据key值去缓存中取出对应key值存储的缓存对象;
- 判断从缓存中根据特定的key值取出的数据是否为空。即是否命中;
- 如果命中,返回缓存结果;
- 如果没有命中,
4.1 去数据库中查询数据,直到查询到结果;
4.2 将key和查询的结果分别作为key和value存储到缓存中;
4.3 将查询结果返回。
key值的确定
statementId+rowBounds+传递给JDBC的SQL+传递给JDBC的参数值。
性能
SqlSession的生存时间很短,一般对一个SqlSession对象执行的操作也不会太多,执行完就消亡。
对一个SqlSession而言,只要执行update、delete、insert就会将这个SqlSession中对应的一级缓存清空。
可以手动释放SqlSession对象中缓存。
二级缓存
二级缓存是Mapper级别的缓存。不同的mapper之间的二级缓存之间相互不影响。需要在配置文件中进行配置。
使用规则
- 在Mybatis配置文件中打开总开关
<stttings>
<setting name="cacheEnabled" value="true"/>
</settings>
2.在需要开启二级缓存的Mapper中加入cache标签
</cache>
3.在使用二级缓存的实体类中实现Serializable接口。
二级缓存参数
flushInterval:刷新间隔。不设置时,缓存只有在调用时被刷新。
size:缓存对象的数目和运行环境的可用内存资源数目。默认为1024。
readOnly:只读的缓存返回的是缓存对象的相同实例,因此这些对象不能被修改。可读写的缓存返回的是对象的拷贝。很安全。所以一般默认为false。
eviction:收回策略。
LUR:最近最少使用的。移除最长时间不被使用的对象。
FIFO:先进先出。按照对象进入缓存的顺序来移除对象。
SOFT:软引用。移除基于垃圾回收器状态和软引用规则的对象。
WEAK:弱引用。更积极的移除基于垃圾回收器和弱引用规则的对象。
应用场景与局限性
应用在查询请求多且对查询结果的实时性要求不高。
局限性是对细粒度的数据级别的缓存实现不好。
自定义缓存
需要实现Mybatis提供的接口:org.apache.ibatis.cache.Cache。