Mybatis二级缓存引起的数据问题

4 篇文章 0 订阅

今天看了mybatis二级缓存的原理,发现原来是session关闭时更新二级缓存。忽然想到这样的话缓存中就是最近关闭的session中的一级缓存数据,而不是最新的数据。于是做了实验,果然证实。这样子的话使用mybatis二级缓存貌似会很危险。因为并发访问情况下各个sqlsession关闭的时间顺序并不能确保。下面是测试代码片段((mybatis自带的二级缓存,配置:LRU算法)

        //初始时,数据库中id为12的员工为王老三
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        SqlSession sqlSession4 = sqlSessionFactory.openSession();

        EmployeesMapper mapper = sqlSession.getMapper(EmployeesMapper.class);
        EmployeesMapper mapper2 = sqlSession2.getMapper(EmployeesMapper.class);
        EmployeesMapper mapper3 = sqlSession3.getMapper(EmployeesMapper.class);
        EmployeesMapper mapper4 = sqlSession4.getMapper(EmployeesMapper.class);

        EmployeesBean emp = mapper.getEmployee(12);
        System.out.println("emp:"+emp); //找到王老三

        mapper2.updateEmp(new EmployeesBean(12, "老四", "李", "北京")); //更新为李老四
        sqlSession2.commit();  //提交李老四

        EmployeesBean emp2 = mapper2.getEmployee(12); //从数据库查找李老四

        System.out.println("emp2:"+emp2); //显示李老四

        sqlSession2.close(); //李老四进入二级缓存

        EmployeesBean emp3 = mapper3.getEmployee(12); //从缓存找到李老四
        System.out.println("emp3:"+emp3);
        sqlSession3.close(); //二级缓存更新为李老四
        sqlSession.close(); //二级缓存更新为王老三
        EmployeesBean emp4 = mapper4.getEmployee(12); //难道是王老三?
        System.out.println("emp4:"+emp4); //果然又是你,王老三

        sqlSession4.close();

输出结果如下(把日志前半部分省略了, **为本人追加的注解):

...] - Cache Hit Ratio [com.testmybatis.EmployeesMapper]: 0.0
...] - ==>  Preparing: select id, last_name, first_name, city from Employees where id = ? 
...] - ==> Parameters: 12(Integer)
...] - <==      Total: 1
 emp:EmployeesBean{id=12, last_name='老三', first_name='王', city='西安'} **找到王老三
...] - ==>  Preparing: update Employees set last_name=?, first_name=?, city=? where id=? 
...] - ==> Parameters: 老四(String), 李(String), 北京(String), 12(Integer)
...] - <==    Updates: 1                                                 **更新为李老四
...] - Cache Hit Ratio [com.testmybatis.EmployeesMapper]: 0.0
...] - ==>  Preparing: select id, last_name, first_name, city from Employees where id = ? 
...] - ==> Parameters: 12(Integer)
...] - <==      Total: 1
 emp2:EmployeesBean{id=12, last_name='老四', first_name='李', city='北京'}  **找到李老四
...] - Cache Hit Ratio [com.testmybatis.EmployeesMapper]: 0.3333333333333333
 emp3:EmployeesBean{id=12, last_name='老四', first_name='李', city='北京'}  **从二级缓存找到李老四
...] - Cache Hit Ratio [com.testmybatis.EmployeesMapper]: 0.5
 emp4:EmployeesBean{id=12, last_name='老三', first_name='王', city='西安'}  **从二级缓存又找到王老三

Process finished with exit code 0

补充:利用mybatis-encache代替mybatis自带的缓存,测试结果没有发生上述问题,具体原因待空闲时看个究竟。

缓存修改为mybatis-ehcache后,问题依旧。之前误以为没问题了,是因为数据修改后没有复原,再次运行结果一直是李老四。

mybatis-ehcache

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值