Deep Dive into MyBatis Core Architecture: The Six Swordmen and Essential Components
This article introduces MyBatis's underlying architecture by explaining the six core interfaces—SqlSession, Executor, StatementHandler, ParameterHandler, ResultSetHandler, and TypeHandler—detailing their roles, key methods, caching mechanisms, and how they are instantiated within a Spring Boot environment.
MyBatis has become a widely used persistence framework for Java, and this article explores its core architecture by focusing on six essential components, referred to as the "Six Swordmen".
Environment Versions : The examples are based on MyBatis 3.5 and SpringBoot 2.3.3.RELEASE .
The Six Swordmen are the following interfaces:
SqlSession
Executor
StatementHandler
ParameterHandler
ResultSetHandler
TypeHandler
Each component plays a specific role in the execution flow, as illustrated by the accompanying diagram.
SqlSession
SqlSession is the central API for executing commands, obtaining mappers, and managing transactions. It provides around twenty methods, including statement execution, transaction control, cache handling, and mapper retrieval.
Statement Execution Methods
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<T> Cursor<T> selectCursor(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)The selectOne method returns a single result, while selectList returns multiple rows; if the expected cardinality is uncertain, selectList is safer.
Methods insert , update , and delete return the number of affected rows.
Additional overloads accept a RowBounds argument to limit result sets, similar to MySQL's LIMIT clause.
<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds)
<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds)
void select(String statement, Object parameter, ResultHandler
handler)
void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler
handler)RowBounds stores the offset and limit for pagination.
Batch Update Method
List<BatchResult> flushStatements()When ExecutorType.BATCH is used, this method executes and clears the batched statements.
Transaction Control Methods
void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)MyBatis does not auto‑commit by default; developers can force commit or rollback when managing JDBC transactions directly.
Local Cache Method
void clearCache()MyBatis maintains a first‑level (session) cache and an optional second‑level cache. The local cache lives for the duration of a SqlSession and can be limited to statement scope via localCacheScope=STATEMENT .
Mapper Retrieval
<T> T getMapper(Class<T> type)Example: UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
Executor
The Executor is the core scheduler that generates SQL, executes statements, and handles caching. Its hierarchy includes:
BaseExecutor (abstract template class)
CachingExecutor (adds second‑level cache)
SimpleExecutor (direct execution)
BatchExecutor (batch processing)
ReuseExecutor (reuses JDBC Statements)
Key snippets:
private
List
queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
// uses first‑level cache (localCache)
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
List
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
return list;
} finally {
localCache.removeObject(key);
}
} @Override
public
List
query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache();
if (cache != null && ms.isUseCache() && resultHandler == null) {
List
list = (List
) tcm.getObject(cache, key);
if (list == null) {
list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list);
}
return list;
}
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}Spring Boot creates a CachingExecutor by default because cacheEnabled is true.
StatementHandler
Responsible for preparing the JDBC Statement and setting parameters. Implementations include:
SimpleStatementHandler (plain Statement)
PreparedStatementHandler (PreparedStatement)
CallableStatementHandler (CallableStatement for stored procedures)
RoutingStatementHandler (routes to the appropriate handler)
ParameterHandler
Replaces placeholders in SQL with actual parameter values. The sole implementation is DefaultParameterHandler , whose key method is setParameters .
TypeHandler
Converts between Java types and JDBC types during parameter setting and result retrieval. MyBatis provides many built‑in handlers; custom handlers are needed for special cases such as storing a Java object as a JSON string.
ResultSetHandler
Transforms the JDBC ResultSet into a List or Cursor . The default implementation is DefaultResultSetHandler , which maps rows according to the mapper's resultType or resultMap .
Conclusion
The article gives an introductory overview of MyBatis's core components, laying the groundwork for deeper source‑code analysis in future posts.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.