千家信息网

如何理解Mybatis源码中的Cache

发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,这篇文章将为大家详细讲解有关如何理解Mybatis源码中的Cache,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。缓存的使用场景通过复杂业务计算得来的
千家信息网最后更新 2025年01月31日如何理解Mybatis源码中的Cache

这篇文章将为大家详细讲解有关如何理解Mybatis源码中的Cache,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

缓存的使用场景

  • 通过复杂业务计算得来的数据,在计算过程中可能耗费大量的时间,需要将数据缓存

  • 读多写少的数据

缓存设计的要点

  • 缓存的容量

  • 缓存的有效时间

实践中可能存在的问题

缓存穿透

访问的缓存不存在,直接去访问数据库。通常查找的key没有对应的缓存,可以设计为返回空值,不去查找数据库。

缓存雪崩

大量的缓存穿透会导致有大量请求,访问都会落到数据库上,造成缓存雪崩。所以如果访问的key在缓存中找不到,不要直接去查询数据库,也就是要避免缓存穿透,可以设置缓存为永久缓存,然后通过后台定时更新缓存。也可以为缓存更新添加锁保护,确保当前只有一个线程更新数据。

Mybatis中的缓存分析与学习

MyBatis的一级缓存和二级缓存

一级缓存

  • 使用范围:SESSION,STATEMENT。默认为SESSION,如果不想使用一级缓存,可以修改为STATEMENT,每次调用后都会清掉缓存。

//STATEMENT或者SESSION,默认为SESSION
  • 一级缓存执行的流程:

//BaseExecutor.querypublic  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());   ...    List list;    try {      ...      //先根据cachekey从localCache去查      list = resultHandler == null ? (List) localCache.getObject(key) : null;      if (list != null) {        //若查到localCache缓存,处理localOutputParameterCache        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);      } else {        //从数据库查        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);      }    } finally {      //清空堆栈      queryStack--;    }    ...    if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {        // issue #482            //如果是STATEMENT,清本地缓存        clearLocalCache();      }    return list;  }
  • 什么情况下有效?在,一个sqlSession打开和关闭的范围内,所以,如果被Spring托管并且没有开启事务,那么一级缓存是失效的。

  • 注意: 打开两个sqlsession: sqlsession1,sqlsession2,sqlsession1.select从一级缓存中取数据,sqlsession2更新此条数据,sqlsession1.select再次获取数据,还是缓存中的。

二级缓存

  • SessionFactory层面给各个SqlSession 对象共享

  • 怎么配置:

 (或@CacheNamespace) ,或@CacheNamespace//每个select设置