Mybatis缓存机制

一级缓存

使用原生生成sqlsession来请求则可以走一级缓存

public class Test {
    public static void main(String[] args) throws IOException {
        String config = "mybatis-config.xml";
        InputStream is = Resources.getResourceAsStream(config);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        System.out.println(session.selectOne("selectUserByID", 1));
        // 同一个session的相同sql查询,将会使用一级缓存 
        System.out.println(session.selectOne("selectUserByID", 1));
        // 参数改变,需要重新查询
        System.out.println(session.selectOne("selectUserByID", 2));
        // 清空缓存后需要重新查询
        session.clearCache();
        System.out.println(session.selectOne("selectUserByID", 1));
        // session close以后,仍然使用同一个db connection
        session.close();
        session = factory.openSession();
        System.out.println(session.selectOne("selectUserByID", 1));
    }
}

通过spring集成获取mapper接口则不行。虽然Mapper是通过MapperFactoryBean单例生成的,但是依然没有一级缓存,因为spring集成mybatis则会动态代理sqlSessionProxy生成sqlsession导致取到的不一致。
在这里插入图片描述
在这里插入图片描述
然而如果有事务的话,事务里的sqlsession是同一个。
一级缓存的脏数据产生原因,另外一个sqlsession更新了数据所以拿到了脏数据。

总结
  1. MyBatis一级缓存的生命周期和SqlSession一致。
  2. MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
  3. MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

二级缓存

mapper级缓存,即作用于全局的缓存,在mybatis配置文件中开启,默认是关闭的。可以多个sqlsession实现共享。该缓存作用于mapper的namespace下,而实现机制和mysql一致,及sql相同则返回缓存数据。
但是不同的namespace下的请求即使sql相同也是不能走到缓存的,一级缓存及二级缓存走缓存的共同点是通过Statement Id + Offset + Limmit + Sql + Params来判断是否走缓存。
当多表查询时关联表被其他namespace更新时无法知悉,所以读缓存得到的是脏数据,可以使用Cache ref,让 ClassMapper 引用 StudenMapper 命名空间,这样两个映射文件对应的SQL操作都使用的是同一块缓存了。不过这样会导致缓存粒度变大。

总结
  1. MyBatis的二级缓存相对于一级缓存来说,实现了 SqlSession 之间缓存数据的共享,同时粒度更加的细,能够到namespace 级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。
  2. MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。
  3. 在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis、Memcached等分布式缓存可能成本更低,安全性也更高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值