Java Mybatis - 一级缓存


介绍

默认情况下,Mybatis 只开启一级缓存,一级缓存只是相对于同一个 SqlSession 而言。所以在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象连续调用同一个 Mapper 方法,往往只执行一次SQL,不会再次发送 SQL 到数据库。

源码

DefaultSqlSession selectList 方法

public class DefaultSqlSession implements SqlSession {

  public  List selectList(String statement, Object parameter, RowBounds rowBounds) {
    MappedStatement ms = configuration.getMappedStatement(statement);
    return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
  }
}

BaseExecutor query 方法

public abstract class BaseExecutor implements Executor {

  protected PerpetualCache localCache;

  public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler){
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
  }

public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql){
    List list;
    // 一级缓存中取数据
    list = resultHandler == null ? (List) localCache.getObject(key) : null;
    if (list != null) {
      handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
    } else {
      list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
    }
    return list;
  }
}

PerpetualCache getObject 方法

public class PerpetualCache implements Cache {
  //一级缓存的本质就是一个 HashMap
  private final Map cache = new HashMap();

  public Object getObject(Object key) {
    return this.cache.get(key);
  }
}