Mybatis—SqlSession—Executor

目录

Executor接口(执行器):

Executor接口源码:

BaseExecutor部分源码:

SimpleExecutor源码:

BatchExecutor源码:

ReuseExecutor源码:

CachingExecutor源码:


Executor接口(执行器):

生命周期局限于SqlSession,实现类为BaseExecutor(一级缓存)、CachingExecutor(二级缓存)。BaseExecutor是抽象类,有三个子类。
1.SimpleExecutor: 最简单的执行器,拼接完SQL之后,直接交给StatementHandler去执行,不做额外的操作。
2.BatchExecutor:  批处理执行器,通过批量操作来优化性能。通常需要注意的是批量更新操作,内部有缓存的实现,用完后要调用flushStatements清除缓存。
3.ReuseExecutor:  可重用的执行器,重用的对象是Statement,会缓存同一个sql的Statement,省去Statement重建。通过一个HashMap来维护Statement对象的,由于当前Map只在该session中有效,用完后要调用flushStatements清除Map。

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;
      List<BatchResult> flushStatements() throws SQLException;
      // 事务提交
      void commit(boolean required) throws SQLException;
      // 事务回滚
      void rollback(boolean required) throws SQLException;
      // 创建缓存的键对象
      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();
      void setExecutorWrapper(Executor executor);
    }

BaseExecutor部分源码:

    构造方法:
    public abstract class BaseExecutor implements Executor {
          protected BaseExecutor(Configuration configuration, Transaction transaction) {
                this.transaction = transaction;
                this.deferredLoads = new ConcurrentLinkedQueue<DeferredLoad>();
                // 一级缓存
                this.localCache = new PerpetualCache("LocalCache");
                this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
                this.closed = false;
                this.configuration = configuration;
                this.wrapper = this;
          }
    }

    update(insert、update、delete操作都会调此方法,会清空一级缓存):
    @Override
    public int update(MappedStatement ms, Object parameter) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
        if (closed) {
          throw new ExecutorException("Executor was closed.");
        }
        // 数据变更操作会清空一级缓存
        clearLocalCache();
        return doUpdate(ms, parameter);
     }

   query(先查缓存,再查数据):
   @Override
   public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameter);
        // 创建一级缓存的键对象
        CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
        // 调用下面的 query 方法
        return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
   }

   @SuppressWarnings("unchecked")
   @Override
   public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
        if (closed) {
          throw new ExecutorException("Executor was closed.");
        }
        if (queryStack == 0 && ms.isFlushCacheRequired()) {
          clearLocalCache();
        }
        List<E> list;
        try {
          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);
          }
        } finally {
          queryStack--;
        }
        if (queryStack == 0) {
          for (DeferredLoad deferredLoad : deferredLoads) {
            deferredLoad.load();
          }
          // issue #601
          deferredLoads.clear();
          if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
            // issue #482
            clearLocalCache();
          }
        }
        return list;
   }

   createCacheKey(一级缓存通过HashMap实现,根据SQL的ID、参数、SQL、分页参数、JDBC的参数信息构成):
   // 创建 CacheKey 对象
   @Override
   public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
        if (closed) {
          throw new ExecutorException("Executor was closed.");
        }
        CacheKey cacheKey = new CacheKey();
        // MappedStatement的id
        cacheKey.update(ms.getId());
        // 分页参数的offset
        cacheKey.update(rowBounds.getOffset());
        // 分页参数的limit
        cacheKey.update(rowBounds.getLimit());
        // SQL语句本身
        cacheKey.update(boundSql.getSql());
        // 传递给jdbc的参数
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
        // mimic DefaultParameterHandler logic
        for (ParameterMapping parameterMapping : parameterMappings) {
              if (parameterMapping.getMode() != ParameterMode.OUT) {
                Object value;
                String propertyName = parameterMapping.getProperty();
                if (boundSql.hasAdditionalParameter(propertyName)) {
                  value = boundSql.getAdditionalParameter(propertyName);
                } 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) {
          // issue #176
          cacheKey.update(configuration.getEnvironment().getId());
        }
        return cacheKey;
   }

SimpleExecutor源码:

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;
            try {
              Configuration configuration = ms.getConfiguration();
              StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
              stmt = prepareStatement(handler, ms.getStatementLog());
              return handler.update(stmt);
            } finally {
              closeStatement(stmt);
            }
          }

          @Override
          public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
            Statement stmt = null;
            try {
              Configuration configuration = ms.getConfiguration();
              StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
              stmt = prepareStatement(handler, ms.getStatementLog());
              return handler.<E>query(stmt, resultHandler);
            } finally {
              closeStatement(stmt);
            }
          }

          @Override
          protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
            Statement stmt = prepareStatement(handler, ms.getStatementLog());
            return handler.<E>queryCursor(stmt);
          }

          @Override
          public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
            return Collections.emptyList();
          }

          private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
            Statement stmt;
            Connection connection = getConnection(statementLog);
            stmt = handler.prepare(connection, transaction.getTimeout());
            handler.parameterize(stmt);
            return stmt;
          }
    }

BatchExecutor源码:

    public class BatchExecutor extends BaseExecutor {
          public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;
          private final List<Statement> statementList = new ArrayList<Statement>();
          private final List<BatchResult> batchResultList = new ArrayList<BatchResult>();
          // 上一次的SQL语句
          private String currentSql;
          // 上一次的MappedStatement 对象
          private MappedStatement currentStatement;
          // 因为调用父类的构造方法,所以 BatchExecutor 自己的私有属性 currentSql和currentStatement 开始都为null
          public BatchExecutor(Configuration configuration, Transaction transaction) {
            super(configuration, transaction);
          }
          @Override
          public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
              final Configuration configuration = ms.getConfiguration();
              final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
              final BoundSql boundSql = handler.getBoundSql();
              final String sql = boundSql.getSql();
              final Statement stmt;
              // 第一次肯定是false,进入else分支,currentSql和currentStatement被初始化,后面进入false分支则进行更新
            if (sql.equals(currentSql) && ms.equals(currentStatement)) {
              // 取上一次的 Statement 对象
              int last = statementList.size() - 1;
              stmt = statementList.get(last);
              applyTransactionTimeout(stmt);
             handler.parameterize(stmt);//fix Issues 322
              BatchResult batchResult = batchResultList.get(last);
              batchResult.addParameterObject(parameterObject);
            } else {
              Connection connection = getConnection(ms.getStatementLog());
              stmt = handler.prepare(connection, transaction.getTimeout());
              handler.parameterize(stmt);    //fix Issues 322
              // currentSql和currentStatement 更新为此次的对象
              currentSql = sql;
              currentStatement = ms;
              statementList.add(stmt);
              batchResultList.add(new BatchResult(ms, sql, parameterObject));
            }
              // handler.parameterize(stmt);
              handler.batch(stmt);
              return BATCH_UPDATE_RETURN_VALUE;
          }
    }

ReuseExecutor源码:

    public class ReuseExecutor extends BaseExecutor {
          private final Map<String, Statement> statementMap = new HashMap<String, Statement>();

          // 调用父类构造器
          public ReuseExecutor(Configuration configuration, Transaction transaction) {
            super(configuration, transaction);
          }

          private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
            Statement stmt;
            BoundSql boundSql = handler.getBoundSql();
            String sql = boundSql.getSql();
            if (hasStatementFor(sql)) {
              // 如果缓存了该SQL,则返回其Statement对象
              stmt = getStatement(sql);
              applyTransactionTimeout(stmt);
            } else {
              // 如果没有缓存该SQL,则创建SQL的Statement,并加入缓存
              Connection connection = getConnection(statementLog);
              stmt = handler.prepare(connection, transaction.getTimeout());
              putStatement(sql, stmt);
            }
            handler.parameterize(stmt);
            return stmt;
          }

          // 是否缓存了这个 sql
          private boolean hasStatementFor(String sql) {
            try {
              return statementMap.keySet().contains(sql) && !statementMap.get(sql).getConnection().isClosed();
            } catch (SQLException e) {
              return false;
            }
          }

          // 返回指定sql的 Statement
          private Statement getStatement(String s) {
            return statementMap.get(s);
          }

          // 添加SQL和Statement
          private void putStatement(String sql, Statement stmt) {
            statementMap.put(sql, stmt);
          }
    }

CachingExecutor源码:

public class CachingExecutor implements Executor {
        // 持有的 Executor, 最终的操作都由该对象实现
        private final Executor delegate;
        private final TransactionalCacheManager tcm = new TransactionalCacheManager();

        public CachingExecutor(Executor delegate) {
            this.delegate = delegate;
            delegate.setExecutorWrapper(this);
        }

        public int update(MappedStatement ms, Object parameterObject) throws SQLException {
            this.flushCacheIfRequired(ms);
            return this.delegate.update(ms, parameterObject);
        }

        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) {
                this.flushCacheIfRequired(ms);
                if (ms.isUseCache() && resultHandler == null) {
                    this.ensureNoOutParams(ms, 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);
        }
            // 是否清空二级缓存
            private void flushCacheIfRequired(MappedStatement ms) {
            Cache cache = ms.getCache();
            if (cache != null && ms.isFlushCacheRequired()) {
                this.tcm.clear(cache);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值