前言

缓存的具体执行过程可以关注
3、MyBatis中关于mapper的执行过程

一级缓存

代码位置

org.apache.ibatis.executor.BaseExecutor#query();

  1. // 一级缓存的存储对象
  2. protected PerpetualCache localCache

image.png
image.png

介绍

1、一级缓存默认开启,所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
注意:MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象。commit之后,缓存消失

Key 的组成

一级缓存的key主要是 statementId+sql语句+参数+值+DB类型 )

二级缓存也是这个key

image.png

关闭一级缓存

参考 https://zhuanlan.zhihu.com/p/151664093

  • 全局设置 mybatis.configuration.local-cache-scope=statement ,则查询之后即便放入了一级缓存,但存放完立马就给清了,下一次还是要查数据库;原因如图中截图部分。

image.png

  • statement 设置 flushCache=”true” ,则查询之前先清空一级缓存,还是得查数据库;

    1. <select id="queryById" resultMap="baseMap" flushCache="true">
    2. select * from user where id = ${id}
    3. </select>
  • 设置随机数,如果随机数的上限足够大,那随机到相同数的概率就足够低,也能类似的看成不同的数据库请求,那缓存的 key 都不一样,自然就不会匹配到缓存。

    • 例如 两次查询分别用 (int)Math.random()1000 (int)Math.random()10000 ;where #{randomString}=#{randomString}

      清空一级缓存

      更新的时候,不管更新什么东西,都会清空sqlSession下的所有缓存。
      image.png

      二级缓存

      代码位置

      org.apache.ibatis.executor.CachingExecutor#query()
      1. // 二级缓存的存储对象
      2. private final TransactionalCacheManager tcm = new TransactionalCacheManager();
      image.png
      image.png

      介绍

      SqlSessionFactory层面上的二级缓存默认是不开启的,二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置就可以开启缓存了

      开启二级缓存

      XML文件配置就可以开启缓存
      在select标签内使用 useCache=true。
      image.png