一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情。
一、Mybatis缓存介绍
内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 为了使它更加强大而且易于配置,我们对 MyBatis 3 中的缓存实现进行了许多改进。
默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
<cache/>
当添加上该标签之后,会有如下效果:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
在进行配置的时候还会分为一级缓存和二级缓存:
一级缓存:线程级别的缓存,是本地缓存,sqlSession级别的缓存二级缓存:全局范围的缓存,不止局限于当前会话
1、一级缓存的使用
一级缓存是sqlsession级别的缓存,默认是存在的。在下面的案例中,大家发现我发送了两个相同的请求,但是sql语句仅仅执行了一次,那么就意味着第一次查询的时候已经将结果进行了缓存
1-1、创建DeptMapper.xml查询方法
1-2、测试
可以发现第一次查询走了数据库查询操作,而第二次仅把数据输出,没有进行数据库查询操作
1-3、可以看下同个执行方法内,两个sqlSession
可以看到虽然是同一个会话内,但是有不同的sqlSession,即使查询条件数据一样,也不会从缓存中查询,而是从数据库查询。
1-4、同一个sqlSession即使不同的条件查询同样的数据也不会走缓存
如下,通过不同的参数查询同一条数据,也是各自从数据库查询,不会走缓存的。
2、一级缓存的设置
Mybatis 全局设置中有个localCacheScope 属性值有两个,分别为:
SESSION(默认):会缓存一个会话中执行的所有查询,当前会话中再次查询相同的语句都会直接从缓存中查询,不再查询数据库。
STATEMENT:本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存
3、总结
Mybatis一级缓存的
特性:
1、默认就开启了,也可以通过设置localCacheScope=STATEMENT来设置关闭。
2、作用域是基于sqlSession(默认),一次数据库操作会话
3、mybatis缓存是根据当前sql以及命名空间,根据statement生成hashcode等进行处理当做key,然后数据当做value存储,因此不同的sql即使数据一致,也不会走缓存,如下图
这样每次执行sql去缓存通过key去查找的时候,即使数据一致,但是key不一致,就无法获得数据。
4、缓存默认实现PerpetualCache,使用map进行存储的
5、查询完就会进行存储
失效情况:
1、不同的sqlSession会使一级缓存失效
2、同一个sqlSession,但是查询语句不一样,也会让缓存失效。
3、同一个sqlSession,查询语句一样,期间执行了任意增删改查操作,缓存也会失效
4、可以通过sqlSession.clearCache() 清除缓存