mybatis 缓存示例图:
mybatis 一级缓存:
信息。
得到用户信息,将用户信息存储到一级缓存中。
如果sqlsSession.去执行commit 操作(执行插入、更新、删除),清空sqlsession.中的一级缓存,这样做的目的为了
让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取
用户信息。
EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO
from EMP
where EMPNO = ?:7369
一个service 方法中包括很多mapper方法调用。
service{
//开始执行时,开启事务,创建Sqlsession 对象
//第一次调用mapper.的方法findUserByld(1)
//第二次调用mapper.的方法findUserByld(1),从一级缓存中取数据
//方法结束,sqlsession关闭
如果是执行两次service 调用查询相同的用户信息,不走一级缓存,因为session方法结束,sqlsession就关闭,一
级缓存就清空。
首先开启mybatis.的二级缓存。
sqlSession1去查询用户id 为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。
如果SqlSession3 去执行相同mapper.下sgl; 执行commit 提交,清空该mapper.下的二级缓存区域的数据。
sqlSession2 去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。
二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlsession可以共享一个UserMapper.的二级缓存区域。UserMapper.有一个二级缓存区域(按namespace分)
其它mapper.也有自己的二级缓存区域(按namespace分)。
每一个namespace 的mapper.都 有一个二缓存 区域,两个mapper的namespace 如果相同,这两个mapper.执行sql
查询到数据将存在相同的二级缓存区域中。
配置步骤:在mybatis配置文件中加入:
在要缓存的Mapper中加入
假如说,已开启二级缓存的Mapper中有个statement要求禁用怎么办,那也不难,只需要在statement中设置useCache=false就可以禁用当前select语句的二级缓存,也就是每次都会生成sql去查询,ps:默认情况下默认是true,也就是默认使用二级缓存
在mapper的同一个namespace中,如果有其他insert、update、delete操作后都需要执行刷新缓存操作,来避免脏读。这时我们只需要设置statement配置中的flushCache=“true“属性,就会默认刷新缓存,相反如果是false就不会了。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。 size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。 readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
回收测量
可用的收回策略有, 默认的是 LRU:
1. LRU – 最近最少使用的:移除最长时间不被使用的对象。
2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
mybatis引入ehcache作为二级缓存
pom.xml 导入相关的jar包
<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache --> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.5.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache --> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.1.0</version> </dependency>
加入ehcache的配置文件ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache> <diskStore path="d:/ehcache/"></diskStore> <!-- 默认缓存配置 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <!-- User缓存配置 --> <cache name="User" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> </ehcache>
在mapper文件中的cache标签下添加type属性。
进入EhcacheCache类,发现它继承了Cache接口。其实:mybatis中引入ehcache就是引入继承了chache接口的类
mybatis中的原生二级缓存,不支持多表联查的缓存,所以需要引入ehcache等缓存插件,这样做的好处还可以实现分布式和集群。
应用场景.
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis 二级缓
存技术降低数据库访问量,提高访问速度,业务场景比如: 耗时较高的统计分析sql、电话
账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis 每隔一段时间自动清空缓存,根据
数据变化频率设置缓存刷新间隔flushInterval,比如设置为30 分钟、60 分钟、24小时等,
根据需求而定。
局限性.
mybatis 二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求: 对商品信息进
行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如
果使用mybatis 的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新
其它商品的信息,因为mybaits 的二级缓存区域以mapper 为单位划分,当一个商品信息变
化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针
对性缓存。