This is the 26th day of my participation in the August Text Challenge.More challenges in August

Sequence diagram

sequenceDiagram
participant A as DefaultSqlSession
participant B as CachingExecutor
participant C as MappedStatement
participant D as SqlSource
participant E as Executor

A ->> B : query
B ->> C : getBoundSql
C ->> D : getBoundSql
D -->> C : BoundSql
C -->> B : BoundSql
B ->> B : createCacheKey
B ->> E : createCacheKey
E -->> B : CacheKey
B ->> B : query
B ->> E : query
E -->> B : List<E>

The detailed steps

DefaultSqlSession#selectList

  • MappedStatement is added to the Configuration object and see the select of Mybatis source | insert | update | delete tags
/** * Query result list *@param<E> The type of the list element returned *@paramStatement SQL statement *@paramParameter Specifies the parameter object *@paramRowBounds Page turn restrictions *@returnResult object list */
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
        /** * set MappedStatement mapping, see {@link XMLStatementBuilder#parseStatementNode()}
         */
        MappedStatement ms = configuration.getMappedStatement(statement);
        CacheEnabled is enabled by default. Therefore, CachingExecutor * is used to fetch executors. See {@link Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)}
         */
        return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
    } finally{ ErrorContext.instance().reset(); }}Copy the code

CachingExecutor#query

@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    // Get BoundSql, which contains the executable SQL and the parameter mapping of the response
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    // Use the actual Executor to generate the cache key
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    // Use the actual Executor to execute the query
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
Copy the code

MappedStatement#getBoundSql

public BoundSql getBoundSql(Object parameterObject) {
    // Get executable SQL
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    // Get the parameter mapping
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    // Determine whether the parameter mapping is empty. If so, use the default parameter mapping (configured parameterMap or parameterType).
    if (parameterMappings == null || parameterMappings.isEmpty()) {
        boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
    }

    // check for nested result maps in parameter mappings (issue #30)
    // Check the embedded result set mapping
    for (ParameterMapping pm : boundSql.getParameterMappings()) {
        String rmId = pm.getResultMapId();
        if(rmId ! =null) {
            ResultMap rm = configuration.getResultMap(rmId);
            if(rm ! =null) { hasNestedResultMaps |= rm.hasNestedResultMaps(); }}}return boundSql;
}
Copy the code

CachingExecutor#query

  • If the level-2 cache exists, the query is performed through the cache. If the level-2 cache does not exist, the query results are cached.
  • Level 2 cache resolution location, see Mybatis source mappers tag resolution
/** * query data in database **@paramMs mapping statement *@paramParameterObject parameterObject *@paramRowBounds Page turn restrictions *@paramResultHandler resultHandler *@paramKey The cached key *@paramBoundSql query statement *@param<E> Result type *@returnResult list@throws SQLException
 */
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
        throws SQLException {
    // Get the cache corresponding to MappedStatement. Possible results are caches for that namespace, caches for other shared namespaces, and no caches
    Cache cache = ms.getCache();
    // If the mapping file is not set to 
      
        or 
       
        , the cache variable is null
       
      
    if(cache ! =null) { // Cache exists
        // Determine whether to clear level 2 cache before statement execution, and if so, clear level 2 cache
        flushCacheIfRequired(ms);
        if (ms.isUseCache() && resultHandler == null) { // This statement uses caching and has no result handler
            // Level 2 cache does not support CALLABLE statements with output parameters
            ensureNoOutParams(ms, boundSql);
            @SuppressWarnings("unchecked")
            // Read the result from the cache
            List<E> list = (List<E>) tcm.getObject(cache, key);
            if (list == null) { // No results in the cache
                // Execute to the wrapped actuator
                list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                // Cache the result returned by the wrapped executor
                tcm.putObject(cache, key, list); // issue #578 and #116
            }
            returnlist; }}// Execute by the wrapped actual actuator
    return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
Copy the code

Mybatis defaultsQlssession #selectList