Mybatis高级进阶之缓存机制
缓存机制的应用:
mybatis为我们提供了查询缓存,用于减轻数据库压力,提高数据库性能
我们在平常的查询中,如果缓存中有相应的数据,就不用再去从数据库获取,减少了一部分的性能损耗,可以大大的提高系统的性能
mybatis的缓存机制有几种?
mybatis提供了2种:一级缓存和二级缓存
一级缓存(sqlsession级别的缓存)
在操作数据库时,需要构造sqlsession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据
不同的sqlsession之间的缓存区域是互相不影响的。
二级缓存(mapper级别的缓存)
多个sqlsession去操作同一个mapper的sql语句,此时多个sqlsession可以共用该二级缓存,所得到的数据会存在二级缓存区域
二级缓存是跨sqlsession的(跨多个session)
二级缓存相比一级缓存的范围更大(按namespace来划分)可以在对应的映射文件中进行体现,多个sqlsession可以共享一个二级缓存
缓存的详解
一级缓存原理
一级缓存是maybatis默认支持的
图解:
执行流程:
第一次发起查询sql查询用户id为1002的学生,先去找缓存中是否有id为1002的学生,如果没有,再去数据库查询学生信息。得到学生信息,将学生信息存储到一级缓存中。
如果sqlsession执行了commit操作(插入,更新,删除),会清空sqlsession中的一级缓存,避免脏读
第二次发起查询id为1002的学生,缓存中如果找到了,直接从缓存中获取学生信息
代码实现讲解:
测试默认的一级sqlSession缓存:
注意代码中使用的是同一个sqlSession
代码:
运行结果:
我们发现sql查询语句只执行了一次,就得到了两条查询的结果
这就验证了默认的一级缓存(sqlSession级别缓存)的存在
介绍如何清除缓存,并进一步验证一级缓存的存在
清除缓存的几种方式:
// sqlSession.clearCache();//手动清除缓存
// sqlSession.commit();//等同于增、删、改来看 (清空缓存)
此处只开放一个验证:
运行结果:
此时我们不难发现相同的sql语句到数据库查询了两次才得到全部的结果
二级缓存原理
图解:
如何实现二级缓存?
我们需要进行手动开启
1.在mybatis的核心配置文件中要进行如下的配置:
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
2.需要将映射的javapojo类实现序列化
3.在对应的映射文件xxxmapper中:
<!--开启本Mapper的namespace下的二级缓存-->
<cache></cache>
对二级缓存进行测试:
多个不同的sqlSession下
java代码:
运行结果:
我们可以发现在不同的sqlSession下,sql查询语句只执行了一次就查询出了所有的结果,开启二级缓存成功。
执行流程:
sqlsession1查询学生id为1001的信息,查询到之后,会将查询数据存储到二级缓存中。
如果sqlsession3去执行相同mapper下sql,执行commit提交,会清空该mapper下的二级缓存区域的数据
sqlsession2查询学生id为1001的信息, 去缓存找 是否存在缓存,如果存在直接从缓存中取数据
禁用二级缓存:
在statement中可以设置useCache=false,禁用当前select语句的二级缓存,默认情况为true
<select id="findStudentById" parameterType="int" resultType="com.duanping.pojo.Student" useCache="false">
select * from student where id =#{id}
</select>
在实际开发中,针对每次查询都需要最新的数据sql,要设置为useCache=“false” ,禁用二级缓存
flushCache标签:刷新缓存(清空缓存)
<select id="findStudentById" parameterType="int" resultType="com.duanping.pojo.Student" flushCache="true">
select * from student where id =#{id}
</select>
一般下执行完commit操作都需要刷新缓存,flushCache="true 表示刷新缓存,可以避免脏读
应用场景:
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
局限性:
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,
此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,
当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。