`
234390216
  • 浏览: 10194081 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:460821
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1771877
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1395481
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:393917
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:678253
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:529320
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1178774
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:462010
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:150169
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:66890
社区版块
存档分类
最新评论

Mybatis的Executor介绍(一)

阅读更多

5       MybatisExecutor介绍(一)

 

目录

 

5       MybatisExecutor介绍(一)

5.1        SimpleExecutor

5.2        ReuseExecutor

5.3        BatchExecutor

5.4        Executor的选择

5.4.1         默认的Executor

 

       Mybatis中所有的Mapper语句的执行都是通过Executor进行的,ExecutorMybatis的一个核心接口,其定义如下。从其定义的接口方法我们可以看出,对应的增删改语句是通过Executor接口的update方法进行的,查询是通过query方法进行的。虽然Executor接口的实现类有BaseExecutorCachingExecutor,而BaseExecutor的子类又有SimpleExecutorReuseExecutorBatchExecutor,但BaseExecutor是一个抽象类,其只实现了一些公共的封装,而把真正的核心实现都通过方法抽象出来给子类实现,如doUpdate()doQuery()CachingExecutor只是在Executor的基础上加入了缓存的功能,底层还是通过Executor调用的,所以真正有作用的Executor只有SimpleExecutorReuseExecutorBatchExecutor。它们都是自己实现的Executor核心功能,没有借助任何其它的Executor实现,它们是实现不同也就注定了它们的功能也是不一样的。Executor是跟SqlSession绑定在一起的,每一个SqlSession都拥有一个新的Executor对象,由Configuration创建。

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;

 

  List<BatchResult> flushStatements() throws SQLException;

 

  void commit(booleanrequired) throws SQLException;

 

  void rollback(booleanrequired) 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(booleanforceRollback);

 

  boolean isClosed();

 

  void setExecutorWrapper(Executor executor);

 

}

 

       下面是BaseExecutor的源码,我们可以看看它是怎么实现Executor接口的,是怎么开放接口给子类实现的。

public abstract class BaseExecutor implements Executor {

 

  private static final Log log = LogFactory.getLog(BaseExecutor.class);

 

  protected Transaction transaction;

  protected Executor wrapper;

 

  protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;

  protected PerpetualCache localCache;

  protected PerpetualCache localOutputParameterCache;

  protected Configuration configuration;

 

  protected int queryStack = 0;

  private boolean closed;

 

  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;

  }

 

  @Override

  public Transaction getTransaction() {

    if (closed) {

      throw new ExecutorException("Executor was closed.");

    }

    returntransaction;

  }

 

  @Override

  public void close(boolean forceRollback) {

    try {

      try {

        rollback(forceRollback);

      } finally {

        if (transaction != null) {

          transaction.close();

        }

      }

    } catch (SQLException e) {

      // Ignore.  There's nothing that can be done at this point.

      log.warn("Unexpected exception on closing transaction.  Cause: " + e);

    } finally {

      transaction = null;

      deferredLoads = null;

      localCache = null;

      localOutputParameterCache = null;

      closed = true;

    }

  }

 

  @Override

  public boolean isClosed() {

    return closed;

  }

 

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

  }

 

  @Override

  public List<BatchResult> flushStatements() throws SQLException {

    return flushStatements(false);

  }

 

  public List<BatchResult> flushStatements(boolean isRollBack) throws SQLException {

    if (closed) {

      throw new ExecutorException("Executor was closed.");

    }

    return doFlushStatements(isRollBack);

  }

 

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

    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;

  }

 

  @Override

  public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {

    if (closed) {

      throw new ExecutorException("Executor was closed.");

    }

    DeferredLoad deferredLoad = new DeferredLoad(resultObject, property, key, localCache, configuration, targetType);

    if (deferredLoad.canLoad()) {

      deferredLoad.load();

    } else {

      deferredLoads.add(new DeferredLoad(resultObject, property, key, localCache, configuration, targetType));

    }

  }

 

  @Override

  public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {

    if (closed) {

      throw new ExecutorException("Executor was closed.");

    }

    CacheKey cacheKey = new CacheKey();

    cacheKey.update(ms.getId());

    cacheKey.update(Integer.valueOf(rowBounds.getOffset()));

    cacheKey.update(Integer.valueOf(rowBounds.getLimit()));

    cacheKey.update(boundSql.getSql());

    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();

    TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();

    // mimic DefaultParameterHandler logic

    for (int i = 0; i < parameterMappings.size(); i++) {

      ParameterMapping parameterMapping = parameterMappings.get(i);

      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;

  }   

 

  @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");

    }

    clearLocalCache();

    flushStatements();

    if (required) {

      transaction.commit();

    }

  }

 

  @Override

  public void rollback(boolean required) throws SQLException {

    if (!closed) {

      try {

        clearLocalCache();

        flushStatements(true);

      } finally {

        if (required) {

          transaction.rollback();

        }

      }

    }

  }

 

  @Override

  public void clearLocalCache() {

    if (!closed) {

      localCache.clear();

      localOutputParameterCache.clear();

    }

  }

 

  protected abstract int doUpdate(MappedStatement ms, Object parameter)

      throws SQLException;

 

  protected abstract List<BatchResult> doFlushStatements(boolean isRollback)

      throws SQLException;

 

  protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)

      throws SQLException;

 

  protected void closeStatement(Statement statement) {

    if (statement != null) {

      try {

        statement.close();

      } catch (SQLException e) {

        // ignore

      }

    }

  }

 

  private void handleLocallyCachedOutputParameters(MappedStatement ms, CacheKey key, Object parameter, BoundSql boundSql) {

    if (ms.getStatementType() == StatementType.CALLABLE) {

      final Object cachedParameter = localOutputParameterCache.getObject(key);

      if (cachedParameter != null && parameter != null) {

        final MetaObject metaCachedParameter = configuration.newMetaObject(cachedParameter);

        final MetaObject metaParameter = configuration.newMetaObject(parameter);

        for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {

          if (parameterMapping.getMode() != ParameterMode.IN) {

            final String parameterName = parameterMapping.getProperty();

            final Object cachedValue = metaCachedParameter.getValue(parameterName);

            metaParameter.setValue(parameterName, cachedValue);

          }

        }

      }

    }

  }

 

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

    try {

      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);

    } finally {

      localCache.removeObject(key);

    }

    localCache.putObject(key, list);

    if (ms.getStatementType() == StatementType.CALLABLE) {

      localOutputParameterCache.putObject(key, parameter);

    }

    returnlist;

  }

 

  protected Connection getConnection(Log statementLog) throws SQLException {

    Connection connection = transaction.getConnection();

    if (statementLog.isDebugEnabled()) {

      return ConnectionLogger.newInstance(connection, statementLog, queryStack);

    } else {

      return connection;

    }

  }

 

  @Override

  public void setExecutorWrapper(Executor wrapper) {

    this.wrapper = wrapper;

  }

 

  private static class DeferredLoad {

 

    private final MetaObject resultObject;

    private final String property;

    private final Class<?> targetType;

    private final CacheKey key;

    private final PerpetualCache localCache;

    private final ObjectFactory objectFactory;

    private final ResultExtractor resultExtractor;

 

    // issue #781

    public DeferredLoad(MetaObject resultObject,

                        String property,

                        CacheKey key,

                        PerpetualCache localCache,

                        Configuration configuration,

                        Class<?> targetType) {

      this.resultObject = resultObject;

      this.property = property;

      this.key = key;

      this.localCache = localCache;

      this.objectFactory = configuration.getObjectFactory();

      this.resultExtractor = new ResultExtractor(configuration, objectFactory);

      this.targetType = targetType;

    }

 

    public boolean canLoad() {

      return localCache.getObject(key) != null && localCache.getObject(key) != EXECUTION_PLACEHOLDER;

    }

 

    public void load() {

      @SuppressWarnings( "unchecked" )

      // we suppose we get back a List

      List<Object> list = (List<Object>) localCache.getObject(key);

      Object value = resultExtractor.extractObjectFromList(list, targetType);

      resultObject.setValue(property, value);

    }

 

  }

 

}

 

5.1     SimpleExecutor

       SimpleExecutorMybatis执行Mapper语句时默认使用的Executor。它提供最基本的Mapper语句执行功能,没有过多的封装的。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());

      returnhandler.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

  public List<BatchResult> doFlushStatements(booleanisRollback) throws SQLException {

    return Collections.emptyList();

  }

 

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {

    Statement stmt;

    Connection connection = getConnection(statementLog);

    stmt = handler.prepare(connection);

    handler.parameterize(stmt);

    returnstmt;

  }

 

}

 

5.2     ReuseExecutor

       ReuseExecutor,顾名思义,是可以重用的Executor。它重用的是Statement对象,它会在内部利用一个Map把创建的Statement都缓存起来,每次在执行一条SQL语句时,它都会去判断之前是否存在基于该SQL缓存的Statement对象,存在而且之前缓存的Statement对象对应的Connection还没有关闭的时候就继续用之前的Statement对象,否则将创建一个新的Statement对象,并将其缓存起来。因为每一个新的SqlSession都有一个新的Executor对象,所以我们缓存在ReuseExecutor上的Statement的作用域是同一个SqlSession。以下是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);

  }

 

  @Override

  public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {

    Configuration configuration = ms.getConfiguration();

    StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);

    Statement stmt = prepareStatement(handler, ms.getStatementLog());

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

    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);

    Statement stmt = prepareStatement(handler, ms.getStatementLog());

    return handler.<E>query(stmt, resultHandler);

  }

 

  @Override

  public List<BatchResult> doFlushStatements(booleanisRollback) throws SQLException {

    for (Statement stmt : statementMap.values()) {

      closeStatement(stmt);

    }

    statementMap.clear();

    return Collections.emptyList();

  }

 

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

    } else {

      Connection connection = getConnection(statementLog);

      stmt = handler.prepare(connection);

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

  }

 

}

 

5.3     BatchExecutor

       BatchExecutor的设计主要是用于做批量更新操作的。其底层会调用StatementexecuteBatch()方法实现批量操作。以下是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>();
  private String currentSql;
  private MappedStatement currentStatement;

  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;
    if (sql.equals(currentSql) && ms.equals(currentStatement)) {
      int last = statementList.size() - 1;
      stmt = statementList.get(last);
     handler.parameterize(stmt);//fix Issues 322
      BatchResult batchResult = batchResultList.get(last);
      batchResult.addParameterObject(parameterObject);
    } else {
      Connection connection = getConnection(ms.getStatementLog());
      stmt = handler.prepare(connection);
      handler.parameterize(stmt);    //fix Issues 322
      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;
  }

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

  @Override
  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
    try {
      List<BatchResult> results = new ArrayList<BatchResult>();
      if (isRollback) {
        return Collections.emptyList();
      }
      for (int i = 0, n = statementList.size(); i < n; i++) {
        Statement stmt = statementList.get(i);
        BatchResult batchResult = batchResultList.get(i);
        try {
          batchResult.setUpdateCounts(stmt.executeBatch());
          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())) { //issue #141
            for (Object parameter : parameterObjects) {
              keyGenerator.processAfter(this, ms, stmt, parameter);
            }
          }
        } catch (BatchUpdateException e) {
          StringBuilder message = new StringBuilder();
          message.append(batchResult.getMappedStatement().getId())
              .append(" (batch index #")
              .append(i + 1)
              .append(")")
              .append(" failed.");
          if (i > 0) {
            message.append(" ")
                .append(i)
                .append(" prior sub executor(s) completed successfully, but will be rolled back.");
          }
          throw new BatchExecutorException(message.toString(), e, results, batchResult);
        }
        results.add(batchResult);
      }
      return results;
    } finally {
      for (Statement stmt : statementList) {
        closeStatement(stmt);
      }
      currentSql = null;
      statementList.clear();
      batchResultList.clear();
    }
  }

}
 

 

5.4     Executor的选择

       既然BaseExecutor下面有SimpleExecutorReuseExecutorBatchExecutorExecutor还有一个CachingExecutor的实现,那我们怎么选择使用哪个Executor呢?默认情况下Mybatis的全局配置cachingEnabled=”true”,这就意味着默认情况下我们就会使用一个CachingExecutor来包装我们真正使用的Executor,这个在后续介绍Mybatis的缓存的文章中会介绍。那我们真正使用的BaseExecutor是怎么确定的呢?是通过我们在创建SqlSession的时候确定的。SqlSession都是通过SqlSessionFactoryopenSession()创建的,SqlSessionFactory提供了一系列的openSession()方法。

public interface SqlSessionFactory {

 

  SqlSession openSession();

 

  SqlSession openSession(boolean autoCommit);

  SqlSession openSession(Connection connection);

  SqlSession openSession(TransactionIsolationLevel level);

 

  SqlSession openSession(ExecutorType execType);

  SqlSession openSession(ExecutorType execType, boolean autoCommit);

  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);

  SqlSession openSession(ExecutorType execType, Connection connection);

 

  Configuration getConfiguration();

 

}

 

       从上面SqlSessionFactory提供的方法来看,它一共提供了两类创建SqlSession的方法,一类是没有指定ExecutorType的,一类是指定了ExecutorType的。很显然,指定了ExecutorType时将使用ExecutorType对应类型的ExecutorExecutorType是一个枚举类型,有SIMPLEREUSEBATCH三个对象。

 

5.4.1  默认的Executor

       而没有指定ExecutorType时将使用默认的ExecutorMybatis默认的ExecutorSimpleExecutor,我们可以通过Mybatis的全局配置defaultExecutorType来进行配置,其可选值也是SIMPLEREUSEBATCH

      <setting name="defaultExecutorType" value="SIMPLE"/>

 

       注意,当Mybatis整合Spring后,Spring扫描后生成的Mapper对象,底层使用的SqlSession都是用的默认的Executor。如果我们需要在程序中使用非默认的Executor时,我们可以在Springbean容器中声明SqlSessionFactoryBean,然后在需要指定Executor的类中注入SqlSessionFactory,通过SqlSessionFactory来创建指定ExecutorTypeSqlSession

 

 

参考文档

       Mybatis源码

 

(注:本文是基于Mybatis3.3.1所写,写于20161224日星期六)

 

 

分享到:
评论
2 楼 234390216 2017-10-10  
snfdf 写道
BatchExecutor的源码帖错了。

谢谢指正,已修复
1 楼 snfdf 2017-10-10  
BatchExecutor的源码帖错了。

相关推荐

    mybatis中的sqlsession--executor实现.zip

    mybatis中的sqlsession--executor实现 mybatis中的sqlsession--executor实现

    springmybatis

    mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis实战教程mybatis in action之三实现数据的增删改查 mybatis实战教程mybatis in action之四实现...

    MyBatis执行SQL并将结果映射成Java对象.docx

    4. SqlSession本身不能直接操作数据库 它是通过底层的Executor执行器接口来操作数据库 Executor接口有两个实现类 一个是普通执行器 一个是缓存执行器(默认) 5. Executor执行器要处理的SQL信息是封装到一个底层对象...

    MyBatis经典面试题详细

    MyBatis简介 MyBatis是什么? ORM是什么 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?...Mybatis中如何指定使用哪一种Executor执行器? Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

    Mybatis常见知识点.md

    - 使得Mybatis一级缓存失效的方法 - Mybatis二级缓存 - Mybatis二级缓存的原理 - Mybatis缓存的缺点 &lt;!-- /TOC --&gt; Mybatis常见知识点 Mybatis优点 - 消除了JDBC硬编码的方式,提高了应用的扩展性。 - ...

    MyBatis框架简单的知识点总结.zip

    MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 ...

    MyBatis框架简单的知识点总结.docx

    MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 ...

    mybatis-r2dbc:MyBatis R2DBC适配器

    对于R2DBC适配来说为ReactiveSqlSessionMapper接口Reactive化,将函数的类型从对象和List调整为Mono和FluxSQL的执行器调整为R2DBC的接口,这里我们不需要类似MyBatis的Executor机制,Reactive框架为R2DBC提供了执行...

    Mybatis原始执行方式Executor代码实例解析

    主要介绍了Mybatis原始执行方式Executor代码实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    MyBatis 源码分析 之SqlSession接口和Executor类

    mybatis框架在操作数据的时候,离不开SqlSession接口实例类的作用,下面通过本文给大家实例剖析MyBatis 源码分析之SqlSession接口和Executor类,需要的朋友参考下吧

    深入剖析MyBatis SQL执行流程:从配置到查询结果的全程追踪

    本文深入分析了MyBatis执行SQL的整个流程,从SqlSessionFactory的创建到SQL语句的执行,揭示了MyBatis工作的内部机制。首先,通过SqlSessionFactoryBuilder,MyBatis解析配置文件生成Configuration对象,并创建...

    Mybatis中SqlSession下的四大对象之执行器(executor)

    mybatis中sqlsession下的四大对象是指:executor, statementHandler,parameterHandler,resultHandler对象。这篇文章主要介绍了Mybatis中SqlSession下的四大对象之执行器(executor),需要的朋友可以参考下

    myBatisDemo.rar

    最近在学习mybatis源码,这是手写的一个关于mybatis查询的代码。里面使用了反射将resultSet的结果集设置到list的对应的对象中,使用了dom4j读取mapper.xml文件,以及executor,sqlsession的实现类。

    mybatis:mybatis源码阅读

    拦截器pluginAll作用于Executor,ParameterHandler,ResultSetHandler,StatementHandler 缓存 一级缓存 本地缓存,scope有session(最小)语句,交替打开,更新操作时清空 二级缓存 默认不开启,二级缓存是多个...

    MyBatis简介.docx

    Mybatis 仅可以编写针对 ParameterHandler 、ResultSetHandler 、StatementHandler 、 Executor 这 4 种接口的插件, Mybatis 通过动态代理,为需要拦截的接口生成代理对象以实 现接口方法拦截功能,每当执行这 4 种...

    Mybatis面试题(含答案).pdf

    Mybatis 仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,My b a t i s 使 用 JD K 的 动 态 代 理 , 为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当...

    mybatis Interceptor对UpdateTime自动处理的实现方法

    主要给大家介绍了关于使用mybatis Interceptor对UpdateTime自动处理的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧

    mybatis分页源码手写分页

    并通过executor和autoCommit等参数实例化SqlSession接口的实现类DefaultSqlSession。DefaultSqlSession具体实现了SqlSession中定义的接口。并通过自己持有的Executor接口,委托具体的Executor去执行sql语句完成具体...

    mybatisSource.zip

    MyBatis源码功能演示环境 ,演示MyBatis的Executor 、StatementHandler 、 SQL映射、对象转换 等核心功能

    MyBatis Excutor 拦截器的巧妙用法

    里要讲的巧妙用法是用来实现在拦截器中执行额外 MyBatis 现有方法的用法,并提供了解决拦截Executor时想要修改MappedStatement时解决并发的问题。感兴趣的朋友一起看看吧

Global site tag (gtag.js) - Google Analytics