美文网首页
Mybatis之Executor执行器

Mybatis之Executor执行器

作者: engineer_tang | 来源:发表于2021-03-30 00:14 被阅读0次

    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);
    
    }
    

    执行器子类实现结构图如下:


    image.png

    1. CachingExecutor类

    这里用到了装饰器模式,抽象构件角色是BaseExecutor,具体构件角色是SimpleExecutor、ReuseExecutor、BatchExecutor,这里没有抽象装饰角色,具体装饰角色是CachingExecutor,通过该模式完成了缓存功能的实现。

    2. SimpleExecutor和ReuseExecutor对比

    SimpleExecutor是默认的执行器,每次执行都会创建一个Statement对象,使用完成会调用closeStatement方法比比使用完的Statement。如下所示:


    image.png

    而Reuse使用完成不会关闭Statement,而是会存入自己维护的HashMap结构的statementMap容器中,方便下次复用。


    image.png
    请看ReuseExecutor类的如下代码:
      private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql();
        if (hasStatementFor(sql)) {
          stmt = getStatement(sql);
          applyTransactionTimeout(stmt);
        } else {
          Connection connection = getConnection(statementLog);
          stmt = handler.prepare(connection, transaction.getTimeout());
          putStatement(sql, stmt);
        }
        handler.parameterize(stmt);
        return stmt;
      }
    
      private boolean hasStatementFor(String sql) {
        try {
          return statementMap.keySet().contains(sql) && !statementMap.get(sql).getConnection().isClosed();
        } catch (SQLException e) {
          return false;
        }
      }
    
      private Statement getStatement(String s) {
        return statementMap.get(s);
      }
    
      private void putStatement(String sql, Statement stmt) {
        statementMap.put(sql, stmt);
      }
    

    从如上代码可以知道,每次获取Statement对象时,会先调用hasStatementFor方法看statementMap容器中是否有可直接使用的Statement对象,如果没有就新创建一个,并且缓存到statementMap容器中。

    3. BatchExecutor

    相关文章

      网友评论

          本文标题:Mybatis之Executor执行器

          本文链接:https://www.haomeiwen.com/subject/scgvhltx.html