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