这篇文章将为大家详细讲解有关Mybatis中Executor的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
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; } ...
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<String, Statement> statementMap = new HashMap<String, Statement>(); ... 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); }
SimpleExecutor与ReuseExecutor和BatchExecutor不同,即没有重用Statement,在update时也没有使用StatementHandler的batch方法,而是用了update方法。
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<Cache, TransactionalCache> transactionalCaches = new HashMap<Cache, TransactionalCache>(); 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<Object, Object> entriesToAddOnCommit; private final Set<Object> entriesMissedInCache; public TransactionalCache(Cache delegate) { this.delegate = delegate; this.clearOnCommit = false; this.entriesToAddOnCommit = new HashMap<Object, Object>(); this.entriesMissedInCache = new HashSet<Object>(); } @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
<select id="findByUsername" resultType="Person" parameterType="Person"> select * from person where username=#{username}; </select>
如下List-7,没有参数设置,默认情况下使用的还是SimpleExecutor、RoutingStatementHandler——内部委托给PrepareStatementHandler.
List-7
<select id="findAll" resultType="Person"> select * from person </select>
关于Mybatis中Executor的作用是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。