Mybatis中一级缓存 和 二级缓存的区别
两者区别:一级缓存的作用域是在SqlSession中,二级缓存的作用域是针对mapper做缓存。
一级缓存(本地缓存)
一级缓存是框架默认为我们开启的,我们不需要做任何配置。
例如我们首次查询id为1的用户,mybatis会将该用户的对象存储在一级缓存中;
如果在此中间 sqlSession 执行了commit操作(增删改) ,则mybatis会清空一级缓存的数据 ,这样就能让我们的数据是最新的,避免产生脏读。
当我们再次查 id 为 1 的用户时,mybatis就会去缓存中查找,就不需要再从数据库中去查询。
mybatis一级缓存是默认开启的,是SqlSession级别的缓存,在操作数据库的时候需要创建一个SqlSession,其中有一个HashMap,用于存储缓存数据。不同的SqlSession之间,其缓存数据的HashMap是不同的;
所以当我们多次调用同一个Mapper和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,以后直接先从缓存中取出数据,不会直接去查数据库。但是不同的SqlSession对象,因为不同的SqlSession都是相互隔离的,所以相同的Mapper、参数和方法,他还是会再次发送到SQL到数据库去执行,返回结果。所以我们需要根据需求开启二级缓存
关于二级缓存
二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession可以共用二级缓存,二级缓存是跨 SqlSession 的。
不管Sqlsession 是否相同,只要 mapper 的 namespace相同就能共享数据。也可以称之为 namespace 级别的缓存 。
sqlSession 关闭后(close) ,一级缓存的数据会保存到二级缓存中,新的相同的查询语句就会去二级缓存中去查询。
二级缓存是Mapper级别的缓存,多个SqlSession去操作同一个Mapper中的SQL语句,则这些SqlSession可以共享二级缓存,即二级缓存是跨SqlSession的。
二级缓存的结构图
sqlSession1 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。
如果 SqlSession3 去执行相同 mapper 映射下 sql,执行 commit 提交, 将会清空该 mapper 映射下的二级缓存区域的数据。
sqlSession2 去查询与 sqlSession1 相同的用户信息, 首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据。
如何实现
在 SqlMapCong.xml 文件开启二级缓存
<settings><!全局开启二级缓存(可以省略, 因为默认就是true)><settingname="cacheEnabled"value="true"/></settings>
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为 false代表不开启二级缓存。
配置相关的 Mapper 映射文件
标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。
<mappernamespace="com.itheima.dao.UserDao"><!设置当前的映射文件对应的Mapper使用二级缓存><cache/>...</mapper>
配置 statement 上面的 useCache 属性
将 UserDao.xml 映射文件中的标签中设置 useCache="true"代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。
注意: 针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存
<select id="findByUid" parameterType="int" resultType="User" useCache="true">SELECT * FROM t_user WHERE uid = #{uid}</select>
注意事项
需要将要存储数据的 pojo 实现 Serializable接口,为了将数据取出做反序列化操作, 因为二级的缓存的存储方式多种多样,有可能存储在内存中,也可能储存到磁盘中。如果我们要再取这个缓存的话,就需要反序列化了。所以建议mybatis中的pojo都去实现Serializable接口。
总结
1、当为select语句时:
flushCache默认为false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。
useCache默认为true,表示会将本条语句的结果进行二级缓存。
2、当为insert、update、delete语句时:
flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。
useCache属性在该情况下没有。
当为select语句的时候,如果没有去配置flushCache、useCache,那么默认是启用缓存的,所以,如果有必要,那么就需要人工修改配置。
参考文献:
https://blog.csdn.net/weixin_45286347/article/details/124149359
https://baijiahao.baidu.com/s?id=1672974128982804783&wfr=spider&for=pc