千家信息网

Mybatis中Executor的作用是什么

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,这篇文章将为大家详细讲解有关Mybatis中Executor的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1.BatchExecutorB
千家信息网最后更新 2025年02月01日Mybatis中Executor的作用是什么

这篇文章将为大家详细讲解有关Mybatis中Executor的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

1.BatchExecutor

BatchExecutor与其它的区别是update方法中,使用的是StatementHandler的batch方法,如下List-1

List-1

public class BatchExecutor extends BaseExecutor {  ...  @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);      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 = sql;      currentStatement = ms;      statementList.add(stmt);      batchResultList.add(new BatchResult(ms, sql, parameterObject));    }  // handler.parameterize(stmt);    handler.batch(stmt);    return BATCH_UPDATE_RETURN_VALUE;  } ...

2.ReuseExecutor

ReuseExecutor与其它executor的区别是重用jdbc的Statement,有个map属性,ReuseExecutor的doUpdate、doQuery中,调用prepareStatement时,如下List-2,会根据sql来判断是否已经存在对应的Statement,如果map中已经有了则直接使用,如果不存在,则通过PrepareStatementHandler.prepare方法获取对Statement,之后放入到map中。

List-2

public class ReuseExecutor extends BaseExecutor {  ...  private final Map statementMap = new HashMap();  ...  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);  }

3.SimpleExecutor

SimpleExecutor与ReuseExecutor和BatchExecutor不同,即没有重用Statement,在update时也没有使用StatementHandler的batch方法,而是用了update方法。

4.CachingExecutor

CachingExecutor有点特殊,使用了Delete模式,此外用到了Cache,如下List-3

List-3

public class CachingExecutor implements Executor {  private final Executor delegate;  private final TransactionalCacheManager tcm = new TransactionalCacheManager();  public CachingExecutor(Executor delegate) {    this.delegate = delegate;    delegate.setExecutorWrapper(this);  }...

来看TransactionalCacheManager,如下List-4,通过Cache这个key,得到TransactionalCache,当调用getObject方法时,间接调用TransactionalCache.getObject.

List-4

public class TransactionalCacheManager {  private final Map transactionalCaches = new HashMap();  public void clear(Cache cache) {    getTransactionalCache(cache).clear();  }  public Object getObject(Cache cache, CacheKey key) {    return getTransactionalCache(cache).getObject(key);  }    public void putObject(Cache cache, CacheKey key, Object value) {    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();    }  }

List-5

public class TransactionalCache implements Cache {  private final Cache delegate;  private boolean clearOnCommit;  private final Map entriesToAddOnCommit;  private final Set entriesMissedInCache;  public TransactionalCache(Cache delegate) {    this.delegate = delegate;    this.clearOnCommit = false;    this.entriesToAddOnCommit = new HashMap();    this.entriesMissedInCache = new HashSet();  }  @Override  public Object getObject(Object key) {    // issue #116    Object object = delegate.getObject(key);    if (object == null) {      entriesMissedInCache.add(key);    }    // issue #146    if (clearOnCommit) {      return null;    } else {      return object;    }  }

List-5中,getObject方法中,从委托的cache中getObject如果不是null则返回,不为null则还需要更新统计。

所以mybatis中可以使用二级缓存就是通过这个Cache来实现的。

在没有特殊设置的情况下,mybatis中,如下List-6,默认使用的executor是SimpleExecutor,StatementHandler是RoutingStatementHandler,内部委托给PrepareStatementHandler。

List-6

如下List-7,没有参数设置,默认情况下使用的还是SimpleExecutor、RoutingStatementHandler--内部委托给PrepareStatementHandler.

List-7

关于Mybatis中Executor的作用是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

0