跳转至

MyBatis的缓存

MyBatis的一级缓存

  • 一级缓存是SqlSession级别的,通过一个SqlSession查询的数据会被缓存
    • 下一次查询相同的数据,就会从缓存中直接获取,不会从数据库中重新访问
  • 一级缓存失效的四种情况:
    • 使用了不同的SqlSession
    • 同一个SqlSession,但是查询条件不同
    • 同一个SqlSession,但是两次查询期间执行了一次增删改查的操作
    • 同一个SqlSession,两次查询期间手动清空了缓存

MyBatis的二级缓存

  • 二级缓存是SqlSessionFactory级别的,通过同一个SqlSessionFactory创建的SqlSession查询结果会被缓存
    • 此后如果执行相同的查询语句,结果就会从缓存中获取
  • 开启条件:
    • 在核心配置文件中,设置全局配置属性cacheEnabed="true"
      • 默认即为true
    • 在映射文件中设置标签<cache/>(直接设置即可)
    • 二级缓存必须在SqlSession关闭或提交之后有效
    • 查询的数据所转换的实体类型必须实现序列化接口
  • 二级缓存失效的情况:
    • 两次查询之间执行了任意的增删改

      [!提示] 缓存只作用于cache标签所在的映射文件中的语句,如果混合使用注解与xml映射文件,在共用接口中的语句将不会被默认缓存 需要使用@CacheNamespaceRef注解指定缓存作用域

[!直接使用cache的效果] - 映射语句文件中的所有 select 语句的结果将会被缓存。 - 映射语句文件中的所有 insert、update 和 delete 语句(增删改)会刷新缓存。 - 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。 - 缓存不会定时进行刷新(也就是说,没有刷新间隔)。 - 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。 - 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

二级缓存的相关配置

  • cache标签的属性:
    • eviction缓存回收策略,默认为LRU
      • LRU:(Least Recently Used)最近最少使用的,移除最长时间不被使用的对象
      • FIFO:(First In First Out)先进先出,按对象进入缓存的顺序来移除他们
      • SOFT:软引用,基于垃圾回收器状态和软引用规则移除对象
      • WEAK:弱引用,更积极地基于垃圾收集器状态和弱引用规则移除对象
    • flushInterval刷新间隔,单位为毫秒
      • 默认情况下不进行设置,也就是无刷新间隔
    • size引用数目
      • 代表缓存最多可以存储多少个对象,太大可能导致内存溢出
    • readOnly只读
      • true:只读缓存,会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改,可以提高性能
      • false:读写缓存,会返回缓存对象的拷贝(通过序列化的方式),速度缓慢,但是相对安全

MyBatis缓存查询的顺序

  • 先查询二级缓存
    • 二级缓存中可能存在其他程序已经查出来的数据,可以直接使用
  • 再查询一级缓存
  • 最后查询数据库
  • 关闭SqlSession后,一级缓存中的数据会写入二级缓存