在mybatis中,缓存有两种,一级缓存与二级缓存,我们就来看看mybatis中缓存原理与应用。
备注一下,这是跟着某培训视频做的学习笔记,有些地方是原话,我也不知道怎么分类,是原创呢还不不原创呢,暂时先原创吧,若有侵犯,请联系我删除修改。
一级缓存
mybatis 中的一级缓存是SqlSession级别的缓存,不同的sqlSession之间的缓存数据区域是互不影响的。
为什么呢?
其实在操作数据库时构造的sqlSession对象时,对象中有一个数据结构HashMap用于存储缓存数据。也就形成了不同的sqlSession之间的缓存数据区域是互不影响的。
二级缓存
二级缓存与一级缓存不同,额,好像说了废话。。
在mybatis二级缓存中,级别是mapper的,也就是sqlSession去操作同一个Mapper的sql语句,操作数据库得到的数据会存放在二级缓存区域。所以说二级缓存是跨sqlSession的。
我们来看一张图:
一级缓存工作原理
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
二级缓存工作原理
sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。如果SqlSession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。
二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。
UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。
即:
每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。
二级缓存开启
在核心配置文件SqlMapConfig.xml中加入
<setting name="cacheEnabled" value="true"/>
开启总开关!
在UserMapper.xml中开启二缓存,UserMapper.xml下的sql执行完成会存储到它的缓存区域(结构还是 HashMap)。
可见要开启两个地方!!!
在二级缓存中还需调用pojo类实现序列化接口
如:
原因是:
为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一样在内存。
UserCache配置
在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。
刷新缓存
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
设置statement配置中的flushCache=“true” 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
如下:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。
此处涉及到mybatis 整合ehcache,暂时不做笔记,后期另写(2019年3月18日)
二级应用场景
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
二级缓存局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
最后打一波小广告
我自己公众号