Executor analysis Mybatis source learning sixth day (core process analysis) of

Executor this class, Mybatis although the surface is SqlSession do CRUD, in fact, the underlying unity call this interface is Executor

Here posted about Mybatis query architecture diagram

 

Executor component analysis

Mybatis Executor is one of the core components, the most basic definition database method of operation, SqlSession functions are based on its implementation;

Before analyzing this first look we do not want to know design patterns white, are so before beginning to speak, that's right where I say something template mode

Template mode: an abstract class that defines a public method to perform the way he / template, a subclass can override the implementation as needed, but call the method will be defined in the abstract class execution, the definition of a skeleton algorithm operation, and deferring some steps to subclasses, subclasses such that the template method may not change the structure of an algorithm to redefine the specific implementation of the algorithm;

Template model we should all be familiar with, give some examples of it: on the HttpClient restTemplate, redisTemplate, and so are the standard style template pattern;

Template mode application scenarios:

Encounter process consists of a series of steps need to be performed constituted, the process from the high-level point of view is the same, but to achieve some steps may be different, this time on the need to consider the use of the template pattern.

Next we talk about this Executor it;

Where on the use of template patterns, BaseExecutor is the template mode of abstraction, he realized most of the methods Executor interface, which offers the ability to manage things and cache management, and other abstract methods need to be implemented as a subclass doUpate, doQuery etc. method;

Then talk about Mybatis a complete implementation process it

SqlSession execution

Executor return to unity in the query

Bar code stickers executor.query

1 @Override
2   public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
3     BoundSql boundSql = ms.getBoundSql(parameter);
4     CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
5     return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
6   }

Start getting Sql statement obtained from MappedStatement because the initialization is stored in MappedStatement is, there is not much talked about, want to know you can look at what I wrote before, you can own Baidu

Through the existing four kinds of information to start creating cache CacheKey, As before I can see the specific analysis Cache foundation support module;

 1 @SuppressWarnings("unchecked")
 2   @Override
 3   public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
 4     ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
 5     if (closed) {
 6       throw new ExecutorException("Executor was closed.");
 7     }
 8     if (queryStack == 0 && ms.isFlushCacheRequired()) {
 9       clearLocalCache();
10     }
11     List<E> list;
12     try {
13       queryStack++;
14       list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
15       if (list != null) {
16         handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
17       } else {
18         list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
19       }
20     } The finally {
 21 is        queryStack-- ;
 22 is      }
 23 is      IF (queryStack == 0 ) {
 24        for (DeferredLoad deferredLoad: deferredLoads) {// delay loading of process data
 25          deferredLoad.load ();
 26 is        }
 27        // Issue 601 # 
28        deferredLoads.clear ();
 29        IF (configuration.getLocalCacheScope () == LocalCacheScope.STATEMENT) {// if the current configuration of a cache Sql STATEMENT, immediately a query complete emptying cache
 30          // Issue # 482 
31 is          clearLocalCache ();
 32        }
33     }
34     return list;
35   }

Non-nested query and FlushCache configured true to empty the cache

According to the terms, if only a simple analysis CacheKey query cache, said someone here will ask, MyBatis will check the secondary cache is not it? Do not worry, Mybatis secondary cache is not written here, then later on BaseExecutor indeed direct access to a cache

If a cache hit is returned, if not hit then load the data from the database (There are three ways: Simple | Reuse | Batch), placed in a cache.

BaseExecutor defines such a query skeleton, there were only about a database operation can be modified or overridden by subclasses to achieve a

Interpretation of three implementation class Executor

SimpleExecutor: the default configuration, use PrepareStatement object to access the database, each visit must create a new PrepareStatement objects;

ReuseExecutor: using precompiled PrepareStatement Object Access database, Access, will reuse statement objects in the cache;

BatchExecutor: the ability to achieve batch execute multiple SQL statements;

First come SimpleExecutor

. 1  @Override
 2    public <E> List <E> doQuery (MappedStatement MS, Parameter Object, RowBounds RowBounds, the ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
 . 3      the Statement stmt = null ;
 . 4      the try { 
      // Get Global the Configuration
. 5 the Configuration Configuration = ms.getConfiguration ();
      // Create StatementHandler objects
. 6 StatementHandler Handler = configuration.newStatementHandler (warpper, MS, Parameter, RowBounds, resultHandler, boundSql);
      // StatementHandler object is created stmt, and treated with a placeholder for the prepareStatement
. 7 stmt =the prepareStatement (Handler, ms.getStatementLog ());
      // returns the conversion result set for the specified object by calling ResultSetHandler statementHandler objects
. 8 return Handler <E>. Query (stmt, resultHandler); . 9 } the finally { 10 closeStatement (stmt); 11 } 12 }
1 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
2     Statement stmt;
     // 在这里获取的Connetion
3 Connection connection = getConnection(statementLog); 4 stmt = handler.prepare(connection, transaction.getTimeout()); 5 handler.parameterize(stmt); 6 return stmt; 7 }
. 1  protected Connection the getConnection (the Log statementLog) throws SQLException {
 2      Connection Connection = transaction.getConnection ();
 . 3      IF (statementLog.isDebugEnabled ()) { 
      // returned here is the enhanced dynamic proxy call Connection
      // log to learn mybatis source module on the article prior to printing parameters statement see the like on the first day of study (logging module),
      after // here elegant way to embed the code used in the call chain returns to the print enhancement type
. 4 return ConnectionLogger.newInstance ( Connection, statementLog, queryStack); . 5 } the else { . 6 return Connection; . 7 } . 8 }

Briefly about the call log chain to print the ConnectionLogger -> PrepareStatementLogger -> ResultSetLogger

After say StatementHandler, in fact, it is the template pattern, abstract classes built the skeleton, three sub-class implementation, we can also go to see, nothing difficult

 

Then ReuseExecutor

1 @Override
2   public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
3     Configuration configuration = ms.getConfiguration();
4     StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
5     Statement stmt = prepareStatement(handler, ms.getStatementLog());
6     return handler.<E>query(stmt, resultHandler);
7   }

Like looking at is not it, really nothing different, specific differences in approach prepareStatement

. 1  Private the Statement the prepareStatement (StatementHandler Handler, the Log statementLog) throws SQLException {
 2      the Statement stmt;
 . 3      BoundSql boundSql = handler.getBoundSql ();
 . 4      String SQL = boundSql.getSql (); // Get Sql statement
 . 5      IF (hasStatementFor (SQL) ) {// the Sql statement checks whether the corresponding cache the statement
 . 6        stmt = getStatement (SQL); // Get cache the statement
 . 7        applyTransactionTimeout (stmt); // set a new timeout
 . 8      } the else {// no buffer statement to create statement, the process of creation and SimpleExecutor statement similar
 9        Connection Connection =the getConnection (statementLog); 
 10        stmt = handler.prepare (Connection, transaction.getTimeout ());
 . 11        putStatement (SQL, stmt); // placed in the cache
 12      } 
      // PrepareStatement process using placeholder
13 is handler.parameterize ( stmt); 14 return stmt; 15 }

Do not want to know the cache is definitely Map

 1 private final Map<String, Statement> statementMap = new HashMap<>(); 

Yes this is a detour to it in the cache Map 41 line, well then do not say anything else funny ......

Secondary cache is through packaging decorator to CachingExecutor BaseExecutor, that is, if the secondary cache is turned on, it would CachingExecutor layer of packaging, so that the walk will go first secondary cache cache, if not open, then the secondary cache, then go directly to cache

 1 @Override
 2   public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
 3       throws SQLException {
    // 从MapperStatement中获取二级缓存
4 Cache cache = ms.getCache(); 5 if (cache != null) { 6 flushCacheIfRequired(ms); 7 if (ms.isUseCache() && resultHandler == null) { 8 ensureNoOutParams(ms, boundSql); 9 @SuppressWarnings("unchecked") 10 List<E> list = (List<E>) tcm.getObject(cache, key); 11 if (list == null) {
        // 二级缓存为空,才会调用BaseExecutor.query
12 list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); 13 tcm.putObject(cache, key, list); // issue #578 and #116 14 } 15 return list; 16 } 17 } 18 return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); 19 }

Before Decorator said in Cache module, do not understand please Baidu, or look at what I wrote before Cache Module

Executor of three actuators

Interpretation of SimpleExecutor doQuery by methods found, the Executor commander, his work scheduler three actuators;

StatementHandler: His role is to use the Statement PrepareStatement database or perform operations, Kai connecting role;

 ParameterHandler: Sql statement for precompiled set parameters, SQL statement placeholders corresponds to an element BoundSql.parameterMappings collection, recording a corresponding parameter names and associated attributes of the parameters in this object?

ResultSetHandler: result set returned to the database (the ResultSet) encapsulated returns an instance of the type designated by the user;

Here SqlSession say I do not like to work Executor you do what, you do what I would not do it StatementHandler

Like pre - >> Project Manager - Developer >>

Here the three actuators respectively corresponding to different periods of treatment

StatementHandler -> parameterHandler -> resultSetHandler

Today to finish here, a little late, tomorrow the rest of the point to write about! Sorry

Author: Atlantic Dance

Time: 2020 \ 03 \ 22

Content About: Mybatis

This article from the network, only technology sharing, shall not accept any liability

Guess you like

Origin www.cnblogs.com/flower-dance/p/12549510.html