Mybatis的一级缓存和二级缓存详解

// 核心配置类组件
public class Configuration {
    // 配置默认的执行器
    // SIMPLE 就是普通的执行器;
    // REUSE 执行器会重用预处理语句(PreparedStatement)
    // BATCH 执行器不仅重用语句还会执行批量更新。
    protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;

    // 所有的Mapper缓存(二级缓存对象)
    public Map<String, Cache> caches = new StrictMap<>("Caches collection");

    public Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection").conflictMessageProducer((savedValue, targetValue) -> ". please check " + savedValue.getResource() + " and " + targetValue.getResource());

    public Cache getCache(String id) {
        return caches.get(id);
    }

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
            executor = new Executor.BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
            executor = new Executor.ReuseExecutor(this, transaction);
        } else {
            executor = new Executor.SimpleExecutor(this, transaction);
        }
        // 如果开启了二级缓存,CachingExecutor装饰普通的执行器
        if (cacheEnabled) {
            executor = new Executor.CachingExecutor(executor);
        }
        return (Executor) interceptorChain.pluginAll(executor);
    }
}

public interface Executor {
    ResultHandler NO_RESULT_HANDLER = null;

    // 执行增删改
    int update(MappedStatement ms, Object parameter) throws SQLException;

    // 查询
    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;

    // 游标查询
    <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;

    // 刷新Statements的缓存
    List<BatchResult> flushStatements() throws SQLException;

    // 提交事务
    void commit(boolean required) throws SQLException;

    // 回滚事务
    void rollback(boolean required) throws SQLException;

    // 创建缓存Key
    CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);

    // 是否缓存
    boolean isCached(MappedStatement ms, CacheKey key);

    // 清空本地缓存,也就是一级缓存
    void clearLocalCache();

    // 延迟加载查询
    void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);

    // 获取事务
    Transaction getTransaction();

    // 关闭执行器
    void close(boolean forceRollback);

    // 执行器是否关闭
    boolean isClosed();

    // 包装Executor
    void setExecutorWrapper(Executor executor);


    // 基础的执行器,封装了一些模板方法,通用操作
    public abstract class BaseExecutor implements Executor {

        // 事务对象
        public Transaction transaction;
        // 包装的执行器
        public Executor wrapper;
        // 延迟加载队列
        public ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
        // 一级缓存,通过这里可以看到,一级缓存是保存到Executor中,而Executor和SqlSession是一对一的关系
        // 因此,一级缓存的作用于就是同一个SqlSession
        public PerpetualCache localCache;
        // 参数缓存,存储过程使用
        public PerpetualCache localOutputParameterCache;
        // 配置信息
        public Configuration configuration;
        // 查询的深度,嵌套查询的层次
        public int queryStack;
        // 当前执行器是否关闭
        public boolean closed;


        // 获取事务
        @Override
        public Transaction getTransaction() {
            if (closed) {
                throw new ExecutorException("Executor was closed.");
            }
            return transaction;
        }

        // 关闭执行器
        @Override
        public void close(boolean forceRollback) {
            // 回滚操作,forceRollback: 强制回滚事务
            this.rollback(forceRollback);
            // 如果存在事务,关闭事务
            if (transaction != null) {
                transaction.close();
            }
            // 重置属性
            transaction = null;
            deferredLoads = null;
            localCache = null;
            localOutputParameterCache = null;
            closed = true;
        }

        @Override
        public boolean isClosed() {
            return closed;
        }

        // 更新操作,insert,delete,update
        @Override
        public int update(MappedStatement ms, Object parameter) throws SQLException {
            if (closed) {
                throw new ExecutorException("Executor was closed.");
            }
            // 清空一级缓存
            clearLocalCache();
            // 执行具体的更新操作
            return doUpdate(ms, parameter);
        }

        // 清空statement的缓存
        @Override
        public List<BatchResult> flushStatements() throws SQLException {
            return flushStatements(false);
        }

        // 刷新statement的缓存
        public List<BatchResult> flushStatements(boolean isRollBack) throws SQLException {
            if (closed) {
                throw new ExecutorException("Executor was closed.");
            }
            // 实际完成刷新操作,可能是删除缓存,可能是执行缓存的批量操作,再删除缓存的statement
            return doFlushStatements(isRollBack);
        }

        @Override
        public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
            // 获取SQL的绑定信息
            BoundSql boundSql = ms.getBoundSql(parameter);
            // 创建缓存Key
            CacheKey key = this.createCacheKey(ms, parameter, rowBounds, boundSql);
            // 开始查询
            return this.query(ms, parameter, rowBounds, resultHandler, key, boundSql);
        }

        @Override
        public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
            if (closed) {
                throw new ExecutorException("Executor was closed.");
            }
            // 第一次执行或者嵌套查询执行完毕才会清空缓存,并且这个SQL需要刷缓存
            // 如果没有执行完毕就清空缓存,那么循环依赖触发的嵌套子查询就无法赋值
            // 所以,必须所有的子查询执行完毕之后才能清空缓存
            if (queryStack == 0 && ms.flushCacheRequired) {
                // 清空一级缓存
                clearLocalCache();
            }
            List<E> list;
            // 开始第一次查询,记录查询深度
            queryStack++;
            // 如果存在结果处理器,就不会使用缓存,否则先从缓存中获取数据
            list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
            // 如果缓存中存在数据
            if (list != null) {
                // 处理存储过程中缓存的参数
                handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
            } else {
                // 如果缓存中不存在数据,从数据库加载数据,然后放入缓存一级缓存
                list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
            }

            // 执行完成,层次-1
            queryStack--;
            // 如果执行完成,包括嵌套查询都执行完毕
            // 如果没有执行完毕就清空缓存,那么循环依赖触发的嵌套子查询就无法赋值
            // 所以,必须所有的子查询执行完毕之后才能清空缓存
            if (queryStack == 0) {
                // 当前执行的SQL是否存在需要延迟加载的属性,因为当存在循环依赖等操作,会就值缓存起来,然后设置为延迟加载
                for (DeferredLoad deferredLoad : deferredLoads) {
                    // 执行所有的延迟加载,处理还没有设置的属性值
                    deferredLoad.load();
                }
                // 清空所有的延迟加载属性
                deferredLoads.clear();
                // 如果缓存的作用于为STATEMENT
                if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
                    // 清空缓存,该缓存只在Statement(SQL)级别失效
                    clearLocalCache();
                }
            }
            return list;
        }

        @Override
        public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
            // 获取SQL的绑定信息
            BoundSql boundSql = ms.getBoundSql(parameter);
            // 执行具体的查询操作
            return doQueryCursor(ms, parameter, rowBounds, boundSql);
        }

        // 延迟加载
        @Override
        public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
            if (closed) {
                throw new ExecutorException("Executor was closed.");
            }
            // 创建延迟加载对象,在resultObject中的property属性暂时没有办法赋值,可能出现了循环依赖
            DeferredLoad deferredLoad = new DeferredLoad(resultObject, property, key, localCache, configuration, targetType);
            // 是否可以加载,如果缓存中存在值,表示可以加载,就不需要延迟加载
            if (deferredLoad.canLoad()) {
                // 立即加载,从缓存中获取该属性的值,设置到resultObject中
                deferredLoad.load();
            } else {
                // 无法加载,需要延迟加载的对象数据保存到队列中
                deferredLoads.add(new DeferredLoad(resultObject, property, key, localCache, configuration, targetType));
            }
        }

        //

        /**
         * 生成缓存Key,由以下几部分构成
         * 1. statementId
         * 2. 分页参数(offset,limit)
         * 3. sql
         * 4. 参数值
         * 5. 环境对象的Id
         */
        @Override
        public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
            if (closed) {
                throw new ExecutorException("Executor was closed.");
            }
            // 缓存key由一下几部分组成
            CacheKey cacheKey = new CacheKey();
            // statementId
            cacheKey.update(ms.getId());
            // 分页条件
            cacheKey.update(rowBounds.getOffset());
            cacheKey.update(rowBounds.getLimit());
            // SQL
            cacheKey.update(boundSql.getSql());
            // 获取参数映射
            List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
            // 获取类型转换器注册表
            TypeHandlerRegistry typeHandlerRegistry = ms.configuration.typeHandlerRegistry;
            // 遍历所有的参数映射
            for (ParameterMapping parameterMapping : parameterMappings) {
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    Object value;
                    // 获取属性名
                    String propertyName = parameterMapping.getProperty();
                    // boundSql中的额外设置属性是否存在该属性名
                    if (boundSql.hasAdditionalParameter(propertyName)) {
                        // 获取该属性的值
                        value = boundSql.getAdditionalParameter(propertyName);
                    }
                    // 参数对象是否为null
                    else if (parameterObject == null) {
                        value = null;
                    }
                    // 参数类型是否存在类型转换器
                    else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                        // 直接将参数作为值
                        value = parameterObject;
                    } else {
                        // 从该参数对象中获取该属性对应的值
                        MetaObject metaObject = configuration.newMetaObject(parameterObject);
                        value = metaObject.getValue(propertyName);
                    }
                    // 设置参数值
                    cacheKey.update(value);
                }
            }
            // 如果存在环境对象
            if (configuration.getEnvironment() != null) {
                // 环境对象的Id也作为缓存的标识
                cacheKey.update(configuration.getEnvironment().getId());
            }
            return cacheKey;
        }

        // 当前Key是否被缓存了
        @Override
        public boolean isCached(MappedStatement ms, CacheKey key) {
            return localCache.getObject(key) != null;
        }

        @Override
        public void commit(boolean required) throws SQLException {
            if (closed) {
                throw new ExecutorException("Cannot commit, transaction is already closed");
            }
            // 清空一级缓存
            this.clearLocalCache();
            // 刷新Statements的缓存
            this.flushStatements();
            // 如果必须提交,则提交事务
            if (required) {
                transaction.commit();
            }
        }

        // 回滚
        @Override
        public void rollback(boolean required) throws SQLException {
            if (!closed) {
                // 清空一级缓存
                clearLocalCache();
                // 刷新Statements的缓存
                flushStatements(true);
                // 如果必须回滚,则回滚事务
                if (required) {
                    transaction.rollback();
                }
            }
        }

        // 情况一级缓存
        @Override
        public void clearLocalCache() {
            if (!closed) {
                // 情况一级缓存
                localCache.clear();
                // 情况参数缓存
                localOutputParameterCache.clear();
            }
        }

        // 关闭statement
        public void closeStatement(Statement statement) {
            if (statement != null) {
                statement.close();
            }
        }

        // 应用事务超时
        public void applyTransactionTimeout(Statement statement) throws SQLException {
            StatementUtil.applyTransactionTimeout(statement, statement.getQueryTimeout(), transaction.getTimeout());
        }

        // 处理存储过程中缓存的参数
        public void handleLocallyCachedOutputParameters(MappedStatement ms, CacheKey key, Object parameter, BoundSql boundSql) {
            if (ms.getStatementType() == StatementType.CALLABLE) {
                Object cachedParameter = localOutputParameterCache.getObject(key);
                if (cachedParameter != null && parameter != null) {
                    MetaObject metaCachedParameter = configuration.newMetaObject(cachedParameter);
                    MetaObject metaParameter = configuration.newMetaObject(parameter);
                    for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
                        if (parameterMapping.getMode() != ParameterMode.IN) {
                            String parameterName = parameterMapping.getProperty();
                            Object cachedValue = metaCachedParameter.getValue(parameterName);
                            metaParameter.setValue(parameterName, cachedValue);
                        }
                    }
                }
            }
        }

        // 从数据库中查询数据
        public <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
            List<E> list;
            // 缓存一个固定的标识
            localCache.putObject(key, EXECUTION_PLACEHOLDER);
            // 具体的查询操作
            list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
            // 删除缓存的固定标识
            localCache.removeObject(key);
            // 将查询的结果进行缓存
            localCache.putObject(key, list);
            // 如果是存储过程
            if (ms.getStatementType() == StatementType.CALLABLE) {
                // 将参数缓存
                localOutputParameterCache.putObject(key, parameter);
            }
            // 返回结果
            return list;
        }

        // 获取连接
        public Connection getConnection(Log statementLog) throws SQLException {
            Connection connection = transaction.getConnection();
            if (statementLog.isDebugEnabled()) {
                return ConnectionLogger.newInstance(connection, statementLog, queryStack);
            }
            return connection;
        }

        @Override
        public void setExecutorWrapper(Executor wrapper) {
            this.wrapper = wrapper;
        }


        // 执行更新操作
        public abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;

        // 实际完成刷新操作,可能是删除缓存,可能是执行缓存的批量操作,再删除缓存的statement
        public abstract List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException;

        // 查询操作
        public abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException;

        // 游标查询
        public abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException;

        // 延迟加载类
        public static class DeferredLoad {

            // 结果对象
            public MetaObject resultObject;
            // 属性名称
            public String property;
            // 目标类型
            public Class<?> targetType;
            // 缓存的Key
            public CacheKey key;
            // 一级缓存
            public PerpetualCache localCache;
            // 对象工厂
            public ObjectFactory objectFactory;
            // 结果提取器
            public ResultExtractor resultExtractor;

            // 是否可以加载,如果缓存中存在值,表示可以加载,就不需要延迟加载
            public boolean canLoad() {
                return localCache.getObject(key) != null && localCache.getObject(key) != EXECUTION_PLACEHOLDER;
            }

            // 从缓存中加载数据,处理对象中的循环依赖
            public void load() {
                // 从缓存中获取数据
                List<Object> list = (List<Object>) localCache.getObject(key);
                // 使用工具类将list转换为指定类型的数据
                Object value = resultExtractor.extractObjectFromList(list, targetType);
                // 将转换后的结果设置到结果对象中
                resultObject.setValue(property, value);
            }

        }

    }

    // 简单的执行器
    public class SimpleExecutor extends BaseExecutor {

        public SimpleExecutor(Configuration configuration, Transaction transaction) {
            super(configuration, transaction);
        }

        // 更新操作
        @Override
        public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
            Statement stmt = null;
            // 获取配置类信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
            // 处理Statement,编译SQL,设置参数
            stmt = prepareStatement(handler, ms.getStatementLog());
            // 执行statement的更新操作
            int update = handler.update(stmt);
            closeStatement(stmt);
            return update;
        }

        // 查询操作
        @Override
        public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
            Statement stmt = null;
            // 获取配置信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            // 处理Statement,编译SQL,设置参数等等
            stmt = prepareStatement(handler, ms.getStatementLog());
            // 执行statement处理器的查询操作
            List<E> list = handler.query(stmt, resultHandler);
            closeStatement(stmt);
            return list;
        }

        @Override
        protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
            // 获取配置信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
            // 处理Statement,编译SQL,设置参数等等
            Statement stmt = prepareStatement(handler, ms.getStatementLog());
            // 执行statement的游标查询操作
            Cursor<E> cursor = handler.queryCursor(stmt);
            // 关闭statement
            stmt.closeOnCompletion();
            return cursor;
        }

        // 默认无需刷新缓存,只要在statement编译的SQL会重用或者缓存的时候才有必要刷新
        @Override
        public List<BatchResult> doFlushStatements(boolean isRollback) {
            return Collections.emptyList();
        }

        // 处理Statement,编译SQL,设置参数
        public Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
            Statement stmt;
            // 获取连接
            Connection connection = this.getConnection(statementLog);
            // 处理statement
            stmt = handler.prepare(connection, transaction.getTimeout());
            // 设置参数
            handler.parameterize(stmt);
            return stmt;
        }

    }

    // 可复用的执行器
    public class ReuseExecutor extends BaseExecutor {

        // statement的缓存,key为sql,value为编译sql之后返回的statement对象
        public Map<String, Statement> statementMap = new HashMap<>();

        // 更新操作
        @Override
        public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
            // 获取配置信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
            // 处理statement,编译sql,缓存相同sql的statement,并且设置参数
            Statement stmt = this.prepareStatement(handler, ms.getStatementLog());
            // 使用Statement执行更新操作
            return handler.update(stmt);
        }

        // 查询操作
        @Override
        public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
            // 获取配置信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            // 处理statement,编译sql,缓存相同sql的statement,并且设置参数
            Statement stmt = this.prepareStatement(handler, ms.getStatementLog());
            // 使用Statement执行查询操作
            return handler.query(stmt, resultHandler);
        }

        // 游标查询操作
        @Override
        protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
            // 获取配置信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
            // 处理statement,编译sql,缓存相同sql的statement,并且设置参数
            Statement stmt = this.prepareStatement(handler, ms.getStatementLog());
            // 执行statement处理器的游标查询操作
            return handler.queryCursor(stmt);
        }

        // 刷新所有缓存的statement
        @Override
        public List<BatchResult> doFlushStatements(boolean isRollback) {
            // 关闭所有缓存的statement
            for (Statement stmt : statementMap.values()) {
                closeStatement(stmt);
            }
            // 清空缓存的statement
            statementMap.clear();
            return Collections.emptyList();
        }

        // 处理statement,编译sql,缓存相同sql的statement,并且设置参数
        public Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
            Statement stmt;
            // 获取SQL的绑定信息
            BoundSql boundSql = handler.getBoundSql();
            // 获取SQL
            String sql = boundSql.getSql();
            // 使用缓存了当前SQL的statement对象
            if (this.hasStatementFor(sql)) {
                // 获取缓存的statement
                stmt = this.getStatement(sql);
                // 设置事务超时时间
                applyTransactionTimeout(stmt);
            } else {
                // 获取连接
                Connection connection = this.getConnection(statementLog);
                // 编译SQL
                stmt = handler.prepare(connection, transaction.getTimeout());
                // 缓存当前sql对应的statement
                this.putStatement(sql, stmt);
            }
            // 使用Statement处理器设置参数
            handler.parameterize(stmt);
            return stmt;
        }
    }

    // 批量执行的执行器
    public class BatchExecutor extends BaseExecutor {

        // 批量更新返回的值(为固定值)
        public static int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;
        // 缓存的statement,遇到执行的statemntId(sql)不一样就会将该statement缓存下来,如果一样,则直接从该缓存中获取statement,则这样就不需要重复编译SQL等操作
        public List<Statement> statementList = new ArrayList<>();
        // 缓存的批量结果,批量结果中保存了statementId,sql,和参数信息
        public List<BatchResult> batchResultList = new ArrayList<>();
        // 当前缓存执行的SQL,如果SQL发生改变,一定是最新一次的SQL
        public String currentSql;
        // 当前缓存的Statement(<insert,select...>)映射语句详细信息,如果SQL发生改变,一定是最新一次的MappedStatement
        public MappedStatement currentStatement;

        // 更新操作
        @Override
        public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
            // 获取配置信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
            // 获取SQL的绑定信息
            BoundSql boundSql = handler.getBoundSql();
            // 获取sql
            String sql = boundSql.getSql();
            Statement stmt;
            // 当sql和执行的映射语句没有发生改变(第一次执行就会缓存,第二次就可以直接从缓存中获取)
            if (sql.equals(currentSql) && ms.equals(currentStatement)) {
                // 获取最后一次执行的statemnet
                int last = statementList.size() - 1;
                stmt = statementList.get(last);
                // 设置事务超时时间
                applyTransactionTimeout(stmt);
                // 使用Statement处理器设置参数
                handler.parameterize(stmt);
                // 获取缓存的批量结果对象
                BatchResult batchResult = batchResultList.get(last);
                // 将该参数保存到批量的结果对象中
                batchResult.addParameterObject(parameterObject);
            }
            // sql或者映射语句发生改变
            else {
                // 重新获取连接
                Connection connection = this.getConnection(ms.getStatementLog());
                // 预处理编译SQL
                stmt = handler.prepare(connection, transaction.getTimeout());
                // 使用Statement处理器设置参数
                handler.parameterize(stmt);
                // 缓存SQL和当前映射语句的详细信息MappedStatement
                currentSql = sql;
                currentStatement = ms;
                // 缓存编译sql之后获得的statement对象
                statementList.add(stmt);
                // 保存批量结果对象,该结果对象包含执行的映射语句详细信息和SQL以及参数信息
                batchResultList.add(new BatchResult(ms, sql, parameterObject));
            }
            // 使用Statement执行批量操作
            handler.batch(stmt);
            // 返回固定的批量更新的值
            return BATCH_UPDATE_RETURN_VALUE;
        }

        // 查询操作
        @Override
        public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {

            Statement stmt = null;
            try {
                // 刷新所有缓存的statement
                flushStatements();
                // 获取配置信息
                Configuration configuration = ms.getConfiguration();
                // 创建Statement处理器,并执行插件,用来处理Statement
                StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
                // 重新获取连接
                Connection connection = this.getConnection(ms.getStatementLog());
                // 预处理编译SQL
                stmt = handler.prepare(connection, transaction.getTimeout());
                // 使用Statement处理器设置参数
                handler.parameterize(stmt);
                // 执行statement处理器的查询操作
                return handler.query(stmt, resultHandler);
            } ly {
                closeStatement(stmt);
            }
        }

        // 游标查询操作
        @Override
        protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
            // 刷新所有缓存的statement
            flushStatements();
            // 获取配置信息
            Configuration configuration = ms.getConfiguration();
            // 创建Statement处理器,并执行插件,用来处理Statement
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
            // 重新获取连接
            Connection connection = this.getConnection(ms.getStatementLog());
            // 预处理编译SQL
            Statement stmt = handler.prepare(connection, transaction.getTimeout());
            // 使用Statement处理器设置参数
            handler.parameterize(stmt);
            // 执行statement处理器的游标查询操作
            Cursor<E> cursor = handler.queryCursor(stmt);
            stmt.closeOnCompletion();
            return cursor;
        }

        // 刷新所有缓存的statement
        @Override
        public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
            try {
                List<BatchResult> results = new ArrayList<>();
                if (isRollback) {
                    return Collections.emptyList();
                }
                // 遍历缓存的所有statement
                for (int i = 0, n = statementList.size(); i < n; i++) {
                    // 获取statement
                    Statement stmt = statementList.get(i);
                    // 设置事务超时时间
                    applyTransactionTimeout(stmt);
                    // 获取statement对应的缓存的批量结果对象
                    BatchResult batchResult = batchResultList.get(i);
                    try {
                        // 执行statement的批量操作,并将批量执行的结果保存到批量结果对象中
                        batchResult.setUpdateCounts(stmt.executeBatch());
                        // 获取执行的映射语句SQL
                        MappedStatement ms = batchResult.getMappedStatement();
                        // 获取批量结果对象中缓存的所有参数
                        List<Object> parameterObjects = batchResult.getParameterObjects();
                        // 获取主键生成器
                        KeyGenerator keyGenerator = ms.getKeyGenerator();
                        if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {
                            Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
                            // 执行主键生成器的执行批量处理之后的逻辑
                            jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
                        } else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) {
                            // 遍历批量结果对象中缓存的所有参数
                            for (Object parameter : parameterObjects) {
                                // 给每一个参数执行主键生成器的执行批量处理之后的逻辑
                                keyGenerator.processAfter(this, ms, stmt, parameter);
                            }
                        }
                        // 关闭statemnt
                        closeStatement(stmt);
                    } catch (BatchUpdateException e) {
                        throw new BatchExecutorException(message.toString(), e, results, batchResult);
                    }
                    // 保存当前处理的tatement对应的缓存的批量结果对象,最终需要返回
                    results.add(batchResult);
                }
                return results;
            } ly {
                // 关闭缓存的所有Statement
                for (Statement stmt : statementList) {
                    closeStatement(stmt);
                }
                // 重置缓存sql等信息
                currentSql = null;
                statementList.clear();
                batchResultList.clear();
            }
        }

    }

    // 带有缓存的执行器
    public class CachingExecutor implements Executor {
        // 装饰模式,实际执行SQL的执行器
        public Executor delegate;
        // 事务缓存管理器
        public TransactionalCacheManager tcm = new TransactionalCacheManager();

        public CachingExecutor(Executor delegate) {
            this.delegate = delegate;
            // 将当前执行器设置为代理执行器的包装对象
            delegate.setExecutorWrapper(this);
        }

        @Override
        public Transaction getTransaction() {
            return delegate.getTransaction();
        }

        // 关闭执行器
        @Override
        public void close(boolean forceRollback) {
            try {
                // 处理缓存
                // 如果需要强制回滚
                if (forceRollback) {
                    // 缓存回滚
                    tcm.rollback();
                    return;
                }
                // 缓存提交
                tcm.commit();
            } ly {
                // 关闭执行器
                delegate.close(forceRollback);
            }
        }

        @Override
        public boolean isClosed() {
            return delegate.isClosed();
        }

        // 更新操作
        @Override
        public int update(MappedStatement ms, Object parameterObject) throws SQLException {
            // 刷新缓存如果需要
            flushCacheIfRequired(ms);
            return delegate.update(ms, parameterObject);
        }

        @Override
        public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
            // 刷新缓存如果需要
            flushCacheIfRequired(ms);
            return delegate.queryCursor(ms, parameter, rowBounds);
        }

        @Override
        public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
            BoundSql boundSql = ms.getBoundSql(parameterObject);
            // 创建缓存KEY
            CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
            // 查询操作
            return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
        }

        @Override
        public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
            // 获取该映射语句需要使用的缓存,就是每一个mapper对应的一个缓存的那个缓存(二级缓存)
            Cache cache = ms.getCache();
            // 如果存在缓存
            if (cache != null) {
                // 刷新缓存如果需要
                flushCacheIfRequired(ms);
                // 当前映射语句需要使用缓存,并且没有设置结果集处理器,如果存在结果集处理器,就不会使用缓存
                if (ms.isUseCache() && resultHandler == null) {
                    // 校验存在过程的输出参数,如果存在输出参数,则抛出异常
                    ensureNoOutParams(ms, boundSql);
                    // 从缓存中获取数据
                    List<E> list = (List<E>) tcm.getObject(cache, key);
                    // 如果不存在缓存
                    if (list == null) {
                        // 使用委托执行器执行查询操作
                        list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                        // 缓存当前结果
                        tcm.putObject(cache, key, list);
                    }
                    // 返回结果
                    return list;
                }
            }
            // 不存在缓存
            // 使用委托执行器执行查询操作
            return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
        }

        @Override
        public List<BatchResult> flushStatements() throws SQLException {
            return delegate.flushStatements();
        }

        @Override
        public void commit(boolean required) throws SQLException {
            delegate.commit(required);
            // 执行缓存管理器的提交操作,缓存也需要提交
            tcm.commit();
        }

        @Override
        public void rollback(boolean required) throws SQLException {
            delegate.rollback(required);
            // 如果必须回滚
            if (required) {
                // 执行缓存管理器的回滚操作,缓存也需要回滚
                tcm.rollback();
            }
        }

        public void ensureNoOutParams(MappedStatement ms, BoundSql boundSql) {
            if (ms.getStatementType() == StatementType.CALLABLE) {
                for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
                    if (parameterMapping.getMode() != ParameterMode.IN) {
                        throw new ExecutorException("Caching stored procedures with OUT params is not supported.  Please configure useCache=false in " + ms.getId() + " statement.");
                    }
                }
            }
        }

        @Override
        public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
            return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
        }

        @Override
        public boolean isCached(MappedStatement ms, CacheKey key) {
            return delegate.isCached(ms, key);
        }

        @Override
        public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
            delegate.deferLoad(ms, resultObject, property, key, targetType);
        }

        @Override
        public void clearLocalCache() {
            delegate.clearLocalCache();
        }

        // 刷新缓存如果有必要
        public void flushCacheIfRequired(MappedStatement ms) {
            // 获取该映射语句需要使用的缓存,就是每一个mapper对应的一个缓存的那个缓存
            Cache cache = ms.getCache();
            // 如果存在缓存,并且设置了必须刷新缓存
            if (cache != null && ms.isFlushCacheRequired()) {
                // 清空二级缓存
                tcm.clear(cache);
            }
        }

        @Override
        public void setExecutorWrapper(Executor executor) {
            throw new UnsupportedOperationException("This method should not be called");
        }

    }

}

// 事务缓存管理器,管理所有的二级缓存
public class TransactionalCacheManager {
    // 管理所有的缓存
    // key为二级缓存对象,也就是Mapper.xml对应的缓存
    // value为支持事务的缓存,该缓存装饰了Mapper.xml中的缓存对象
    // 并且内部缓存的数据并不会立即保存到缓存对象中,而是保存到装饰类的暂存区
    // 只有当事务提交的时候才会将装饰类中暂存的数据保存到缓存对象中
    public Map<Cache, TransactionalCache> transactionalCaches = new HashMap<>();

    // 清空指定缓存,实际上是清空事务缓存对象
    public void clear(Cache cache) {
        this.getTransactionalCache(cache).clear();
    }

    // 获取缓存数据,实际上是从事务缓存对象中获取数据
    public Object getObject(Cache cache, CacheKey key) {
        return this.getTransactionalCache(cache).getObject(key);
    }

    // 保存缓存数据,实际上是保存到事务缓存对象中
    public void putObject(Cache cache, CacheKey key, Object value) {
        this.getTransactionalCache(cache).putObject(key, value);
    }

    // 提交事务,将当前管理器管理的所有事务缓存进行提交
    public void commit() {
        for (TransactionalCache txCache : transactionalCaches.values()) {
            txCache.commit();
        }
    }

    // 回滚事务,将当前管理器管理的所有事务缓存进行回滚
    public void rollback() {
        for (TransactionalCache txCache : transactionalCaches.values()) {
            txCache.rollback();
        }
    }

    /**
     * 获取指定缓存的事务缓存对象
     *
     * @param cache mapper.xml对应的缓存对象,每一个mapper.xml如果开启了缓存,都会对应一个缓存对象
     */
    public TransactionalCache getTransactionalCache(Cache cache) {
        // 从这里可知,transactionalCaches中将mapper.xml中的缓存作为了key,那么,不管任何时候
        // 只要是相同的mapper,那么该mapper对应的缓存对象都是同一个(在解析mapper的时候就已经创建了)
        // 因此,通过缓存对象从transactionalCaches缓存中获取出来的事务缓存也是同一个,这就是二级缓存,也就是mapper级别的缓存
        TransactionalCache transactionalCache = transactionalCaches.get(cache);
        // 从这里可以知道,该事务缓存实际上就是将Mapper对应的缓存对象进行装饰
        if (transactionalCache == null) {
            transactionalCache = new TransactionalCache(cache);
        }
        transactionalCaches.put(cache, transactionalCache);
        return transactionalCache;
    }

}

// 带有事务的缓存
public class TransactionalCache implements Cache {

    // 实际操作的缓存对象
    public Cache delegate;
    // 是否在事务提交的时候清空缓存,也就是标识缓存被删除了,而不进行立刻删除
    public boolean clearOnCommit;
    // 提交事务时要将缓存暂存的数据添加到缓存对象中(这个是缓存的暂存对象,只有在事务提交的时候才会真正的保存到缓存中)
    public Map<Object, Object> entriesToAddOnCommit;
    // 不存在缓存数据的KEY,也就是缓存数据为空的Key
    public Set<Object> entriesMissedInCache;

    public TransactionalCache(Cache delegate) {
        this.delegate = delegate;
        this.clearOnCommit = false;
        this.entriesToAddOnCommit = new HashMap<>();
        this.entriesMissedInCache = new HashSet<>();
    }

    // 获取缓存ID
    @Override
    public String getId() {
        return delegate.getId();
    }

    // 获取缓存大小
    @Override
    public int getSize() {
        return delegate.getSize();
    }

    // 获取缓存数据
    @Override
    public Object getObject(Object key) {
        // 获取缓存数据
        Object object = delegate.getObject(key);
        // 如果不存在缓存数据
        if (object == null) {
            // 保存该不存在缓存的KEY
            entriesMissedInCache.add(key);
        }
        // 是否在事务提交的时候清空缓存,也就是标识缓存被删除了,而不进行立刻删除
        if (clearOnCommit) {
            // 返回null,因为需要清空,所以即使有缓存数据也不应该返回
            return null;
        }
        // 返回缓存数据
        return object;
    }

    // 设置缓存
    @Override
    public void putObject(Object key, Object object) {
        // 添加缓存,实际上只是将该数据进行暂存,不会添加到缓存对象中
        // 提交事务时要将缓存暂存的数据添加到缓存对象中(这个是缓存的暂存对象,只有在事务提交的时候才会真正的保存到缓存中)
        entriesToAddOnCommit.put(key, object);
    }

    // 删除缓存
    @Override
    public Object removeObject(Object key) {
        return null;
    }

    // 清空缓存
    @Override
    public void clear() {
        // 是否在事务提交的时候清空缓存,也就是标识缓存被删除了,而不进行立刻删除
        clearOnCommit = true;
        // 清空缓存数据的暂存区
        entriesToAddOnCommit.clear();
    }

    // 提交事务
    public void commit() {
        // 是否在事务提交的时候清空缓存,也就是标识缓存被删除了,现在就正式删除缓存
        if (clearOnCommit) {
            // 实际清空缓存
            delegate.clear();
        }
        // 如果没有标记在事务提交的时候需要清空缓存,那么就不会清空缓存,而是将所有暂存区的缓存进行保存
        //将所有暂存区的缓存进行保存
        this.flushPendingEntries();
        // 重置缓存相关的数据信息
        this.reset();
    }

    // 回滚事务
    public void rollback() {
        // 删除所有不存在缓存数据的Key,因为不存在缓存数据的Key都被保存了,如果某些情况,将这些key又添加了缓存数据,这个时候就将这些key的缓存进行删除
        // 保证这些key是不存在缓存数据的
        unlockMissedEntries();
        // 重置缓存相关的数据信息
        reset();
    }

    // 重置缓存相关的数据信息
    public void reset() {
        clearOnCommit = false;
        // 清空所有暂存区的缓存以及不存在缓存数据的Key信息
        entriesToAddOnCommit.clear();
        entriesMissedInCache.clear();
    }

    // 将所有暂存区的缓存进行保存
    public void flushPendingEntries() {
        // 将暂存区所有的缓存数据正式保存
        for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) {
            delegate.putObject(entry.getKey(), entry.getValue());
        }
        // 将所有不存在缓存数据的Key,也保存到缓存中,值为null
        for (Object entry : entriesMissedInCache) {
            if (!entriesToAddOnCommit.containsKey(entry)) {
                delegate.putObject(entry, null);
            }
        }
    }

    // 删除所有不存在缓存数据的Key,因为不存在缓存数据的Key都被保存了,如果某些情况,将这些key又添加了缓存数据,这个时候就将这些key的缓存进行删除
    // 保证这些key是不存在缓存数据的
    public void unlockMissedEntries() {
        /**
         * {@link TransactionalCache#getObject(Object)}
         */
        for (Object entry : entriesMissedInCache) {
            delegate.removeObject(entry);
        }
    }

}

// Mapper映射SQL的表示形式
// 就是解析(select|insert...)标签的信息
public class MappedStatement {
    // statement(select|insert...)的id
    // 命名空间+方法名
    public String id;
    // 该标签需要使用的缓存
    public Cache cache;
    // 这个SQL是否需要刷新缓存
    public boolean flushCacheRequired;
    // 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来
    // 默认值:对 select 元素为 true
    public boolean useCache;
    // 当执行INSERT、UPDATE或DELETE语句返回数据时会标记为true,来正确地控制事务
    // 判断是否为脏查询
    public boolean dirtySelect;


    public static class Builder {
        public MappedStatement mappedStatement = new MappedStatement();

        public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
            mappedStatement.configuration = configuration;
            mappedStatement.id = id;
            mappedStatement.sqlSource = sqlSource;
            mappedStatement.statementType = StatementType.PREPARED;
            mappedStatement.resultSetType = ResultSetType.DEFAULT;
            mappedStatement.parameterMap = new ParameterMap.Builder(configuration, "defaultParameterMap", null, new ArrayList<>()).build();
            mappedStatement.resultMaps = new ArrayList<>();
            mappedStatement.sqlCommandType = sqlCommandType;
            mappedStatement.keyGenerator = configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
            String logId = id;
            if (configuration.getLogPrefix() != null) {
                logId = configuration.getLogPrefix() + id;
            }
            mappedStatement.statementLog = LogFactory.getLog(logId);
            mappedStatement.lang = configuration.getDefaultScriptingLanguageInstance();
        }

        public MappedStatement build() {
            return mappedStatement;
        }
    }

    // 获取SQL的绑定信息
    public BoundSql getBoundSql(Object parameterObject) {
        // 获取SQL的绑定细腻
        BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
        // 获取该SQL需要使用的参数映射
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        // 如果不存在参数映射信息
        if (parameterMappings == null || parameterMappings.isEmpty()) {
            // 创建一个新的BoundSql
            boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
        }

        // 检查参数映射中的嵌套结果映射
        // <parameterMap id="" type="">
        //    也就是id属性使用resultMap的映射方式,将java参数对象映射到SQL参数中
        //    <parameter property="id" resultMap="rm"></parameter>
        //  </parameterMap>
        for (ParameterMapping pm : boundSql.getParameterMappings()) {
            String rmId = pm.getResultMapId();
            if (rmId != null) {
                ResultMap rm = configuration.getResultMap(rmId);
                if (rm != null) {
                    // 是否存在嵌套的resultMap
                    hasNestedResultMaps |= rm.hasNestedResultMaps();
                }
            }
        }
        return boundSql;
    }

}

// Mapper.xml构建器,解析器
public class XMLMapperBuilder extends BaseBuilder {
    // Mapper.xml/Mapper接口构造者的辅助类
    public MapperBuilderAssistant builderAssistant;

    // 解析该mapper.xml
    public void parse() {
        // 解析xml中的所有标签
        configurationElement(parser.evalNode("/mapper"));
    }

    // 配置mapper
    public void configurationElement(XNode context) {
        // 获取命名空间
        String namespace = context.getStringAttribute("namespace");
        // 不存在抛出异常
        if (namespace == null || namespace.isEmpty()) {
            throw new BuilderException("Mapper's namespace cannot be empty");
        }
        // 设置命名空间
        builderAssistant.setCurrentNamespace(namespace);
        // 解析cacheRef标签
        cacheRefElement(context.evalNode("cache-ref"));
        // 解析cache标签
        cacheElement(context.evalNode("cache"));
    }

    // 解析cacheRef标签,引用缓存
    private void cacheRefElement(XNode context) {
        if (context != null) {
            // 保存缓存的引用信息
            configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
            // 解析cacheRef,将当前Mapper.xml使用的缓存设置为它引用的缓存对象
            builderAssistant.useCacheRef(cacheRefNamespace);
        }
    }

    // 解析cache标签
    public void cacheElement(XNode context) {
        if (context != null) {
            // 获取缓存类型,默认为PERPETUAL
            String type = context.getStringAttribute("type", "PERPETUAL");
            // 获取缓存对应的类型Perpetual
            Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
            // 获取LRU对应的缓存对象
            String eviction = context.getStringAttribute("eviction", "LRU");
            // 获取驱逐方式类型
            Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
            // 获取缓存刷新时间间隔
            Long flushInterval = context.getLongAttribute("flushInterval");
            Integer size = context.getIntAttribute("size");
            boolean readWrite = !context.getBooleanAttribute("readOnly", false);
            boolean blocking = context.getBooleanAttribute("blocking", false);
            // 获取缓存标签中的属性标签配置
            Properties props = context.getChildrenAsProperties();
            // 给该mapper.xml的命名空间创建一个缓存对象保存到配置类中
            builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
        }
    }
}

// Mapper.xml/Mapper接口构造者的辅助类
public class MapperBuilderAssistant extends BaseBuilder {
    // 配置类信息
    private Configuration configuration;
    // 当前Mapper的命名空间
    public String currentNamespace;
    // 当前Mapper使用的Cache对象
    public Cache currentCache;
    // 未解析的缓存引用
    public boolean unresolvedCacheRef;

    public MapperBuilderAssistant(Configuration configuration, String resource) {
        super(configuration);
        this.resource = resource;
    }

    public void setCurrentNamespace(String currentNamespace) {
        this.currentNamespace = currentNamespace;
    }


    /**
     * 应用命名空间,确定元素的唯一标识,也就是将mapper.xml中的元素的加上命名空间来确定该元素的唯一标识
     *
     * @param base        基础元素标识 例如:<resultMap id="xx"></resultMap>
     * @param isReference 是否是引用命名空间,例如:继承了另外文件的元素标识 <resultMap extends="xxx.xxx.resultMap"></resultMap>
     * @return 最终元素的唯一标识
     */
    public String applyCurrentNamespace(String base, boolean isReference) {
        if (base == null) {
            return null;
        }
        // 如果是引用命名空间
        if (isReference) {
            // 如果存在"."直接返回
            if (base.contains(".")) {
                return base;
            }
        } else {
            // 如果该元素的标识以当前命名空间开头,直接返回
            if (base.startsWith(currentNamespace + ".")) {
                return base;
            }
            if (base.contains(".")) {
                throw new BuilderException("Dots are not allowed in element names, please remove it from " + base);
            }
        }
        // 其他情况,一律返回命名空间+"."+基础的元素标识
        return currentNamespace + "." + base;
    }

    // 使用指定命名空间的缓存
    public Cache useCacheRef(String namespace) {
        if (namespace == null) {
            throw new BuilderException("cache-ref element requires a namespace attribute.");
        }
        try {
            // 标注为未解析
            unresolvedCacheRef = true;
            // 获取该命名空间的缓存
            Cache cache = configuration.getCache(namespace);
            // 如果cacheRef引用的命名空间对应的缓存还没被加载,抛出异常
            // 也就是引用的缓存还没加载,后续对该异常进行处理,再次进行解析
            if (cache == null) {
                throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.");
            }
            // 保存当前缓存
            currentCache = cache;
            // 重置缓存引用表示
            unresolvedCacheRef = false;
            // 返回该命名空间的缓存
            return cache;
        } catch (IllegalArgumentException e) {
            throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.", e);
        }
    }

    // 创建指定命名空间的缓存
    public Cache useNewCache(Class<? extends Cache> typeClass, Class<? extends Cache> evictionClass, Long flushInterval, Integer size, boolean readWrite, boolean blocking, Properties props) {
        // 创建缓存对象
        Cache cache = new CacheBuilder(currentNamespace)
                // 指定缓存的实现,默认为PerpetualCache
                .implementation(valueOrDefault(typeClass, PerpetualCache.class))
                // 添加装饰器,带有Lru功能的缓存
                .addDecorator(valueOrDefault(evictionClass, LruCache.class))
                // 设置定时刷新缓存的时间
                .clearInterval(flushInterval)
                // 设置缓存的大系哦啊
                .size(size)
                // 是否支持读写
                .readWrite(readWrite)
                // 是否阻塞
                .blocking(blocking)
                // 设置属性
                .properties(props)
                .build();
        // 保存该缓存
        configuration.addCache(cache);
        // 保存当前缓存对象
        currentCache = cache;
        // 返回创建的缓存
        return cache;
    }

    // 添加Mapper的<insert,select,delete,update>元素的映射语句信息
    public MappedStatement addMappedStatement(String id, SqlSource sqlSource, StatementType statementType,
                                              SqlCommandType sqlCommandType, Integer fetchSize, Integer timeout, String parameterMap, Class<?> parameterType,
                                              String resultMap, Class<?> resultType, ResultSetType resultSetType, boolean flushCache, boolean useCache,
                                              boolean resultOrdered, KeyGenerator keyGenerator, String keyProperty, String keyColumn, String databaseId,
                                              LanguageDriver lang, String resultSets, boolean dirtySelect) {

        // 如果设置了需要引用某个缓存,但是它还未被解析完成,抛出异常,稍后处理这个异常,重新解析,当解析完成缓存的就能解析成功
        if (unresolvedCacheRef) {
            throw new IncompleteElementException("Cache-ref not yet resolved");
        }
        // 应用命名空间,确定元素的唯一标识,也就是将mapper.xml中的元素的加上命名空间来确定该元素的唯一标识
        id = applyCurrentNamespace(id, false);
        // 构造MappedStatement,存储sql相关的所有信息
        MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
                .resource(resource).fetchSize(fetchSize).timeout(timeout).statementType(statementType)
                .keyGenerator(keyGenerator).keyProperty(keyProperty).keyColumn(keyColumn).databaseId(databaseId).lang(lang)
                .resultOrdered(resultOrdered).resultSets(resultSets)
                .resultMaps(getStatementResultMaps(resultMap, resultType, id)).resultSetType(resultSetType)
                .flushCacheRequired(flushCache).useCache(useCache)
                .dirtySelect(dirtySelect)
                /**
                 * 解析Mapper.xml的时候,{@link XMLMapperBuilder#configurationElement}
                 * 通过{@link MapperBuilderAssistant#useCacheRef }和{@link MapperBuilderAssistant#useNewCache}解析缓存
                 * 可以发现,最终currentCache只会保存一个,要么使用<cache/>,要么使用<cache-ref/>,当同时存在,cache会覆盖cache-ref
                 * 并将<cache/>的缓存对象最终会保存到{@link Configuration}对象中
                 */
                .cache(currentCache);
        // 构造MappedStatement
        MappedStatement statement = statementBuilder.build();
        // 保存statement到配置类型
        configuration.addMappedStatement(statement);
        return statement;
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值