Mybatis缓存的那些事

本文深入探讨了MyBatis中的缓存机制,特别是localcache和cache的区别及作用。通过一个具体的代码示例,展示了在Spring事务下,MyBatis如何处理数据缓存,导致数据更新时出现的意外结果。并提供了几种有效的解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天写代码的时候碰到了一个情况 简单的的写了一个小demo

@Test
    @Transactional
    public void test(){
        Role role = new Role();
        role.setRolename("xxxx");
        int insert = roleMapper.insert(role);
        System.out.println(insert);
        Role roleBase = roleMapper.selectByPrimaryKey(role.getId());
        System.out.println(roleBase);
        change(roleBase.getId(),"aaaa");
        change(roleBase.getId(),"bbbb");
        System.out.println(JSONUtils.toJSONString(roleBase));


    }

    private void change(Integer roleId, String s){
        Role role = roleMapper.selectByPrimaryKey(roleId);
        System.out.println(role);
        role.setRolename(s);
    }

对插入数据库的一条数据做了一个change操作,但是并没有传入roleBase这个对象。

输出:

通过观察输出,可以看出通过 selectByPrimaryKey 这个方法查出的对象是同一个对象,而且roleBase的值被改变了。

第一反应就是用了缓存。

之后通过修改mybatis的配置

<settings>
    <setting name="cacheEnabled" value="false"/>
</settings>

不启用缓存,但是查出来的数据依然是一样的,还是同一个对象。

之后通过对selectByPrimaryKey打断点,跟踪执行的流程

这里将数据缓存进了localCache!!!

 

在网上找了一些cache相关的文章

local cache和cache

mybatis提供了两种cache类型:local cache和cache

要特别注意的是,mybatis的local cache是无法关闭的。

那么local cache干了什么?在默认配置情况下,mybatis会将同一session内的查询结果都放在local cache中,这样可以提高性能,避免每次都hit到数据库。

那么cache干了什么呢?和local cache相对的,cache是跨session的,也就是说这个session中缓存的结果,在另外一个session中也能够用到。

 

问题分析

前面已经讲到了在同一session中的查询会将结果缓存,那么这个和我们一开始提到的问题有什么关系呢?聪明的你一定已经想到了,这个问题和启用了事务有关。

实际上mybatis在和spring集成后,会自动将session绑定到事务上,那么就会产生前面提到的问题。

 

解决办法

有以下几种解决办法:

  1. 在mybatis配置文件中localCacheScope=STATEMENT

  2. 在mapper配置文件中,给select设置flushCache=true。需要注意的是,这样会将local cache和cache都清空掉。

  3. 不用事务

缓存参考:https://segmentfault.com/a/1190000008207977

 

测试了1,3两个方法可以结局localcache的问题。2应该也ok

 

学习可以学习美团点评对Mybatis的缓存介绍,讲的很详细了。

https://tech.meituan.com/mybatis_cache.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值