Spring整合mybatis后,为什么会导致一级缓存失效?

Spring整合mybatis后,在注入每个Mapper的时候,都是注入的由mybatis生成的代理对象,在执行每个sql时都是由这个代理对象去执行的,而在生成代理对象的时候,获取的SqlSession是通过一个SqlSessionTemplate生成的一个SqlSessionProxy对象,也就是说在执行比如select类sql的时候都是由这个SqlSessionProxy对象去执行具体sqlSession的selectOne方法去查询数据库的,但是在获取具体的SqlSession的时候会有一个判断,就是判断有没有开启事务(加没加@Transactional注解),如果开启了事务,就会先去ThreadLocal的属性中去取,如果可以取到就直接用,取不到就新建,这样多个sql就会共用一个SqlSession,这时一级缓存就生效了;如果没有开启事务,则每次都是新建SqlSession,这样的话,就是当一个sql执行完后,这个SqlSession的生命周期就完成啦,下一个sql进来又是新的SqlSession,这也就不存在缓存的意义了。这也说明一级缓存失效其实并不是个问题,而是本身设计就是这样的。

其实并不建议开启一级缓存,因为当一级缓存开启后,在一个事务中去执行相同的sql,比如:

 @Transactional //当事务的隔离级别设置为读未提交
	public void test(){
		System.out.println(userMapper.findById());①
		System.out.println(userMapper.findById());②
	}

这时候就会出现这样的情况:

①查询的结果比如是2条数据;但在①执行完,②未执行前,
又在数据库中增加了一条数据,本来②应该查出3条数据,
但因为存在一级缓存,②会直接返回①的结果,这就不是我们想要的结果

当然这还有个问题就是mybatis在源码实现上都没有加Lock,synchronized等加锁机制,为了保证线程安全,这使用了ThreadLocal来修饰一些属性,这就保证了在一个事务中,是用的同一个Sqlsession,从而保证线程安全。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值