MyBatis的缓存机制
- 缓存可以极大的提升数据库的查询效率
在日常工作中,开发人员多数情况下是使用MyBatis的默认缓存配置,但是MyBatis缓存机制有一些不足之处,在使用中容易引起脏数据,形成一些潜在的隐患。
mybatis缓存原理图:
一, mybatis的一级缓存(本地缓存)
Mybatis的一级缓存是SqlSession级别的。一级缓存的作用域是一个SqlSession。Mybatis默认开启一级缓存。
在同一个SqlSession中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则SqlSession的缓存清空。
原文:https://blog.youkuaiyun.com/xu768840497/article/details/79234790
- 一级缓存失效情况
1,不是同一个sqlsession(会话)
2,两次查询条件不一样-----缓存中没有改数据
3,两次查询之间有增删改操作
4,自己手动清除了缓存clearCache
二,mybatis的二级缓存(全局缓存)
Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。
在同一个namespace下的mapper文件中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则二级缓存清空。
使用二级缓存时,由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化。
-
二级缓存运用实例:
1,在mybatis全局配置文件里面开启。
2,在*Mapper.xml文件中加入<cache></cache> 标签
3,cache标签的一些属性
type:cache使用的类型,默认是PerpetualCache,这在一级缓存中提到过。
eviction: 定义回收的策略,常见的有FIFO,LRU。
flushInterval: 配置一定时间自动刷新缓存,单位是毫秒。
size: 最多缓存对象的个数。
readOnly: 是否只读,若配置可读写,则需要对应的实体类能够序列化。
blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。
*4,因为可能会使用到序列化和反序列化的技术,所以相关的pojo要实现序列化接口
- test例子:两个不同的sqlSession,第二次使用缓存数据。
- 注意:!!查询的数据默认是先放在一级缓存之中,当回话被关闭close()或提交commit()后时,才会保存到二级缓存,如果openSession.close()被放到第二个会话查询之后,则还是查询了两次,因为数据并没有被保存到二级缓存之中,而是在一级缓存之中,又是两个不同的会话,所以查询了两次。
三,和缓存有关的设置
1,全局配置里面的cacheEnabled设置为false只能关闭二级缓存,一级缓存默认开启
,
2,每一个select标签都有一个useCache,默认值为true,设置为false时,关闭二级缓存。
3,当flushCache设置为true时(默认),发生增删改,一二级缓存全部都会被清空。
相反,设置为false,缓存就不会被清空
4:
四,扩展
mybatis的缓存是保存在Map集合中,相对简陋,mybatis提供了cache接口,允许我们使用其他强大的缓存器,如:Redis,echcache