【MyBatis】MyBatis一级缓存和二级缓存(1)

简介: 【MyBatis】MyBatis一级缓存和二级缓存

MyBatis自带的缓存有一级缓存和二级缓存


一级缓存


Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。

也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;

第二次以后是直接去缓存中取。

当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。


一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。

如果需要更改一级缓存的范围,可以在Mybatis的配置文件中,在下通过localCacheScope指定。


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

建议不需要修改


需要注意的是

当Mybatis整合Spring后,直接通过Spring注入Mapper的形式,如果不是在同一个事务中每个Mapper的每次查询操作都对应一个全新的SqlSession实例,这个时候就不会有一级缓存的命中,但是在同一个事务中时共用的是同一个SqlSession。

如有需要可以启用二级缓存。


二级缓存


Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。


二级缓存是默认启用的(要生效需要对每个Mapper进行配置),如想取消,则可以通过Mybatis配置文件中的元素下的子元素来指定cacheEnabled为false。


<settings>
  <setting name="cacheEnabled" value="false" />
</settings>


cacheEnabled默认是启用的,只有在该值为true的时候,底层使用的Executor才是支持二级缓存的CachingExecutor。具体可参考Mybatis的核心配置类org.apache.ibatis.session.Configuration的newExecutor方法实现。

可以通过源码看看

...
    public Executor newExecutor(Transaction transaction) {
        return this.newExecutor(transaction, this.defaultExecutorType);
    }
    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? this.defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Object executor;
        if (ExecutorType.BATCH == executorType) {
            executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
            executor = new ReuseExecutor(this, transaction);
        } else {
            executor = new SimpleExecutor(this, transaction);
        }
        if (this.cacheEnabled) {//设置为true才执行的
            executor = new CachingExecutor((Executor)executor);
        }
        Executor executor = (Executor)this.interceptorChain.pluginAll(executor);
        return executor;
    }
...


要使用二级缓存除了上面一个配置外,我们还需要在我们每个DAO对应的Mapper.xml文件中定义需要使用的cache


...
<mapper namespace="...UserMapper">
    <cache/><!-- 加上该句即可,使用默认配置、还有另外一种方式,在后面写出 -->
    ...
</mapper>


具体可以看org.apache.ibatis.executor.CachingExecutor类的以下实现

其中使用的cache就是我们在对应的Mapper.xml中定义的cache。

    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameterObject);
        CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);
        return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }
    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        Cache cache = ms.getCache();
        if (cache != null) {//第一个条件 定义需要使用的cache  
            this.flushCacheIfRequired(ms);
            if (ms.isUseCache() && resultHandler == null) {//第二个条件 需要当前的查询语句是配置了使用cache的,即下面源码的useCache()是返回true的  默认是true
                this.ensureNoOutParams(ms, parameterObject, boundSql);
                List<E> list = (List)this.tcm.getObject(cache, key);
                if (list == null) {
                    list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                    this.tcm.putObject(cache, key, list);
                }
                return list;
            }
        }
        return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

还有一个条件就是需要当前的查询语句是配置了使用cache的,即上面源码的useCache()是返回true的,默认情况下所有select语句的useCache都是true,如果我们在启用了二级缓存后,有某个查询语句是我们不想缓存的,则可以通过指定其useCache为false来达到对应的效果。

如果我们不想该语句缓存,可使用useCache=”false


<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" useCache="false">
        select
        <include refid="Base_Column_List"/>
        from tuser
        where id = #{id,jdbcType=VARCHAR}
    </select>


目录
相关文章
|
3月前
|
缓存 Java 数据库连接
MyBatis的缓存
MyBatis的缓存
|
13天前
|
XML 缓存 Java
MyBatis二级缓存解密:深入探究缓存机制与应用场景
MyBatis二级缓存解密:深入探究缓存机制与应用场景
49 2
MyBatis二级缓存解密:深入探究缓存机制与应用场景
|
1月前
|
存储 缓存 Java
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
|
1月前
|
缓存 Java 数据库连接
mybatis 数据库缓存的原理
MyBatis 是一个流行的 Java 持久层框架,它封装了 JDBC,使数据库交互变得更简单、直观。MyBatis 支持两级缓存:一级缓存(Local Cache)和二级缓存(Global Cache),通过这两级缓存可以有效地减少数据库的访问次数,提高应用性能。
282 1
|
1月前
|
存储 缓存 Java
【MyBaits】4、延迟加载、MyBatis 的缓存
【MyBaits】4、延迟加载、MyBatis 的缓存
22 0
|
2月前
|
SQL 缓存 Java
mybatis缓存详解
mybatis缓存详解
23 0
|
3月前
|
缓存 Java 数据库连接
mybatis的缓存内容(下)
mybatis的缓存内容
29 0
|
3月前
|
SQL 缓存 Java
mybatis的缓存内容(上)
mybatis的缓存内容
31 0
|
3月前
|
缓存 Java 数据库连接
|
3月前
|
缓存 Java 数据库连接
MyBatis支持的缓存刷新模式
MyBatis支持的缓存刷新模式
217 1