mybatis 缓存

一级缓存

在全局配置文件中的 setting 节点中配置 localCacheScope 为 SESSION,表示一级缓存作用域是 SESSION

<setting name="localCacheScope" value="SESSION"/>

一级缓存不能关闭,但是可以更改作用范围,也就是说 value 不能为空,可选的值有 SESSIONSTATEMENT

SESSION 表示当前会话的所有查询都会被缓存;STATEMENT 表示对当前执行的 sql 生效,sql 执行结束就清空缓存。

描述太官方,简言之就是 SESSION 打开一级缓存,STATEMENT 不适用一级缓存

场景1

同一个 SqlSession 查询一样的 MappedStatement,利用缓存

SqlSession1 SqlSession1
queryById(1)
缓存中没有,查询数据库并加入缓存,返回
queryById(1)
缓存命中,直接返回

场景2

不同 SqlSession,查询和更新导致 脏数据

SqlSession1 SqlSession2 SqlSession1
queryById(1)
缓存中没有,查询数据库并加入缓存,返回
updateById(1)
清空 SqlSession2 的缓存
queryById(1)
缓存命中,直接返回

源码就不分析了,大致描述下就行了

  1. Mybatis 打开一个会话会创建一个 SqlSession
  2. 每次创建 SqlSession 里面都会创建一个新的 Executor,Executor 持有一个 PerpetualCache 对象,这个里面就是缓存结果
  3. 当会话结束,也就是调用 SqlSession.close() 时会释放 PerpetualCache
  4. 当会话执行更新操作,也就是调用 SqlSession 的 insert、update、delete 方法会释放 PerpetualCache
  5. 当 SqlSession 调用 clearCache() 时也会释放 PerpetualCache

总结一下:

  1. 一级缓存基于 SqlSession,不能关闭,能更改作用域
  2. 一级缓存的 SESSION 作用域可能产生脏数据,使用 STATEMENT 解决

二级缓存

开启二级缓存

  1. 全局配置文件启用二级缓存

    <settings>
        <!-- 开启二级缓存 -->
    	<setting name="cacheEnabled" value="true"/>
    </settings>
    
  2. 映射文件配置二级缓存

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mj.center.credit.dao.mapper.CreditBusinessBillMapper">
    
        <!-- 当前 mapper 开启二级缓存 -->
        <cache />
    
        <!-- 当前语句加入缓存 -->
        <select useCache="true" id="queryById" resultType="com.mj.center.credit.dao.eo.UserEo">
            select * from t_user where id = #{id}
        </select>
    
        <!-- 当前语句执行后清空当前 mapper 的二级缓存 -->
        <select flushCache="true" id="queryByCode" resultType="com.mj.center.credit.dao.eo.UserEo">
            select * from t_user where code = #{code}
        </select>
    
    </mapper>
    
  3. 返回对象实现序列化接口

cache 配置项

<cache /> 映射文件中简单这样写就行了,没有配置项表示都是用默认的配置,可以手动配置,全部的配置:<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

  1. eviction:淘汰策略
    1. LRU – 最近最少使用的:移除最长时间不被使用的对象(默认)
    2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们
    3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象
    4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
  2. flushInterval:过期时间,单位毫秒,默认不过期
  3. size:缓存大小,表示能存放多少个缓存对象
  4. readOnly:只读模式,默认 true
  5. cachetype:缓存实现类,自定义缓存时配置

select 配置项

  1. useCache:当前 select 使用缓存
  2. flushCache:当前语句执行完就清空缓存

注意事项

  1. 只在单表使用,联表查询不要使用(原因还是会缓存污染,比如 Amapper 联合查询了 a 表和 b 表进行缓存,Bmapper 更新了 b 表数据)
  2. 当为 select 下:flushCache 默认为 false,useCache 默认为 true
  3. 当为 insert、update、delete 下:flushCache 默认为 true,没有 useCache 属性

自定义缓存

需要在映射文件中的 cache 标签指定 cacheType,值是实现了org.apache.ibatis.cache.Cache 的一个类。

用的太少了,当下不整理了,其实现在一二级缓存基本都不会配置,如果需要缓存都是直接考虑 redis 了

posted @ 2023-07-24 16:21  黄光跃  阅读(1)  评论(0编辑  收藏  举报