MyBatis 作为常用的 Java 数据库访问层ORM框架。Mybatis 也为我们提供缓存机制,用于减轻数据库压力,提高数据库性能。
在日常工作中,开发人员多数情况下是使用MyBatis的默认缓存配置,但是MyBatis缓存机制有一些不足之处,在使用中容易引起脏数据,形成一些潜在的隐患。
MyBatis 提供了一级缓存
和二级缓存
。
用于保存用户在一次会话过程中查询的结果
,用户一次会话中只能使用一个sqlSession,一级缓存是自动开启的,不允许关闭(我们也可以自己关闭)。一级缓存,只对当前会话有效。sqlSession1 和 sqlSession 2 是两个会话,如果 sqlSession2 已经修改了数据。sqlSession1 拿到的数据还会是之前缓存的旧数据,并不会拿到最新的数据,这就出现了脏数据的问题。现在我们就需要一个范围更广作用域的缓存,就引出了二级缓存这个概念!!!
MyBatis 一级缓存存在于 Excutor(具体是在 BaseExecutor 类中
),二级缓存是 namespace级别,作用域更大。所以 MyBatis 设计者将二级缓存存放在 Excutor 的包装类 CacheExecutor 中。
、、
这三个标签, flushCache
属性默认为 true
,会自动清空缓存;|||||>>>select
标签就不一样了, flushCache
属性默认为 false
,不会自动清空缓存。不过我们可以根据实际情况,手动来修改该属性二级缓存相当于有两道门,默认只是打开了大门,每个小门的开关没打开,需要我们手动去配置。
大门: mybatis-config.xml 目录
<settings>
<setting name="cacheEnabled" value="true"/>
settings>
小门: 每一个 mapper.xml 目录下,需要我们手动开启缓存。添加一个 标签,就说明当前 namespace 开启了二级缓存,如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.springboot.dao.UserMapper">
<!-- 声明这个 namespace 使用二级缓存 -->
<cache/>
<resultMap id="BaseResultMap" type="com.springboot.entity.User">
...省略...
</resultMap>
<select id="xxx" parameterType="xxx">
...省略..
</select>
你会发现 此属性的存在说明该缓存对象是可以被修改的。如果缓存对象被修改,那么被修改后缓存的对比之前的肯定就不是同一个对象,此时我们就需要返回该缓存对象的一个拷贝,这个拷贝就需要通过序列化来实现了。 所以我们缓存的这个对象,必须实现 Serializable 接口,否则会报错。
readOnly 为 ture 的话,则缓存对象无法修改,就是同一个对象,这样子效率会更高。
readOnly 为 false 的话,这样子更安全。
二级缓存,我们也可以使用 Redis 等其他三方缓存组件,需要引入相关 Jar 包。配置信息如下:
<cache type="org.mybatis.caches.redisCache"
size="512"
eviction="FIFO"
flushInterval="60000"
readOnly="true"/>
<settings>
<setting name="localCacheScope" value="STATEMENT"/>
settings>
<settings>
<setting name="cacheEnabled" value="false"/>
settings>
二级缓存意味着 namespace 下每个方法都会使用缓存。如果某个标签SQL不想使用二级缓存,我们可以为某个指定标签使用 "useCache = false"
来关闭二级缓存。
失效分两种情况:
①当前 nameSpace 下,每一个 sqlSession 会话的 insert、delete、update 操作都会导致数据被修改,二级缓存会失效; ②如果长时间没有被修改,耳机缓存配置中,有一个 flushInterval 属性,到了该属性配置的指定时间,也会自动清空缓存二级缓存还是比较鸡肋,因为只要有其他的mapper(非当前namespace 的 mapper) 也调用了这个 namespace 所在 的 mapper.xml,二级缓存就会被清空。 二级缓存适用于一些查询的场合,诸如BI系统。
其实 MyBatis 一级缓存、二级缓存还是比较鸡肋。MyBatis 在分布式环境下,由于默认的 Cache 实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将 MyBatis 的Cache 接口实现,有一定的开发成本,直接使用 Redis,Memcached 等分布式缓存可能成本更低,安全性也更高。
博主写作不易,来个关注呗
求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙
博主不能保证写的所有知识点都正确,但是能保证纯手敲,错误也请指出,望轻喷 Thanks♪(・ω・)ノ