MyBatis 缓存实现原理

标签(空格分隔): mybatis


缓存概述

  • mybatis存在一级缓存和二级缓存
  • 一级缓存在BaseExecutor中实现,二级缓存在CachingExecutor中实现。
  • mybatis缓存采用了装饰器和委托模式。(LoggingCache、SynchronizedCache是其装饰类)
  • 一级缓存和二级缓存都存放在PerpetualCache对象中,PerpetualCache持有一个Map<Object, Object> Cache属性
    Key为CacheKey,Value为sql执行后的结果集。CacheKey 根据namespace、offset、limit、sql输个属性生成。
  • 二级缓存支持其他缓存介质接入。

立即开始

***Mapper.xml 配置中加入,这里启用了二级缓存。

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
  • evication 表示缓存采用的淘汰策略,flushInterval表示缓存的刷新时间,size表示缓存数量到达多大时刷新,readOnly则表示缓存是否只读。
  • 在mybatis初始化时会把mapper.xml解析成StatementMapper对象,StatementMapper维护一个cache对象,二级缓存是和StatementMapper绑定在一起的。

代码

mybatis-cache

  • 从上面的包名和类名我们可以看出,mybatis的缓存采用了装饰器模式。委托模式在CachingExecutor类中能看出来。

一级缓存

mybatis-baseexecutor-cache

  • 一级缓存在BaseExecutor类中实现,在152行中,如果返回结果不为空,并且能在localCache中get到数据,mybatis就不会再去查询数据库。 其中的localCache是一个PerpetualCache对象。

  • 由于BaseExecutor是BatchExecutor、ReuseExecutor、SimpleExecutor的父类。在执行查询(query)时,mybatis都会判断localCache是否存在缓存,如果存在就返回缓存中的值。言外之意就是一级缓存是默认开启的。

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor 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 (cacheEnabled) {
    executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
    }

  • CachingExecutor 实现了二级缓存,interceptorChain在这里实现了Executor级别的拦截,返回了一个被代理得执行器对象。CachingExecutor持有了一个BaseExecutor的委托对象,这里就是委托模式得运用。

posted @ 2019-07-24 15:57  谭果  阅读(2461)  评论(0编辑  收藏  举报