Mybatis的一级缓存,二级缓存

一级缓存

SqlSession级别的缓存,默认打开,Mybatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个Map对象中,下一次查询直接从缓存中取值
在这个sqlsession中间,有增删改,会清空一级缓存
springboot + mybatis 开启了连接池,会话由mybatis同一管理,在方法不开启事务时,单个select是自动提交(commit)的,提交后会话关闭,不会使用到一级缓存。
开启事务后,才是同一sqlsession

MySql/Oracle中的一级缓存

mysql事务隔离级别为可重复读(ISOLATION_REPEATABLE_READ),在嵌套事务中,内层事务对数据的更改,外层事务无法看见(虽然内层事务已经commit,外层事务也要自己commit后,才能看见其它事务的改动)
而Oracle隔离级别为读已提交(ISOLATION_READ_COMMITTED),内层数据提交后,外层事务可已看见。但是在spring的事务中,如外层先查了这个数据,内层事务修改该条数据,外层事务如重新select查该数据,因为和第一次查是同一sqlsession,会使用一级缓存,看不到该数据变动,可在xml的sql条件中加上 flushCache=“true”,表示在执行sql之前,清除一级缓存。

flushCache应该是对一二级缓存都起作用,有文章写道:开启二级缓存后,update语句的flushCache默认为true,也可手动改为false,修改数据不刷新缓存(不推荐)
所以猜测为:select默认:flushCache=“false” useCache=“true” update:flushCache=“true”

两种一级缓存模式

一级缓存的作用域有两种:session(默认)和 statment,可通过设置 local-cache-scope 的值来切换,默认为 session。
二者的区别在于 session 会将缓存作用于同一个 sqlSesson,而 statment 仅针对一次查询,所以,local-cache-scope: statment 可以理解为关闭一级缓存。

二级缓存

namespace(应用)级别,
全局开关(如设置为false,即使后面的二级缓存配置,也不会生效)
mybatis:
configuration:
cache-enabled: true
默认情况下,mybatis 打开了二级缓存,但它并未生效,因为二级缓存的作用域是 namespace,所以还需要在 Mapper.xml 文件中配置一下才能使二级缓存生效
在mapper文件中配置标签,和useCache="true"表示开启二级缓存,如果useCache没有配置,则会根据标签是不是select来判断useCache的值是true还是false。
在xml中statement中设置useCache=false 则可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认是true(使用二级缓存)
需要注意的是,如果要使用二级缓存,需要让你的实体类实现 Serializable 接口。
只有commit操作后,才会将数据刷到二级缓存中

二级缓存带来的好处远远比不上他所隐藏的危害,二级缓存作用域是namespace,如果对user对象处理,在另一个mapper如OrderMapper.xml中有查询,UserMapper.xml更新了缓存,OrderMapper.xml是无法感知的
联表查询的问题更多
最后还是建议,放弃二级缓存,在业务层使用可控制的缓存代替更好。

缓存的优先级

通过 mybatis 发起的查询,作用顺序为:二级缓存 -> 一级缓存 -> 数据库 ,其中任何一个环节查到不为空的数据,都将直接返回结果
缓存失效
当在一个缓存作用域中发生了 update、insert、delete 动作后,将会触发缓存失效,下一次查询将命中数据库,从而保证不会查到脏数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值