MyBatis Source Code Execution Flow Explained
The article walks through MyBatis’s internal execution pipeline, from loading the configuration file and building a SqlSessionFactory, to creating a SqlSession, generating a MapperProxy for the mapper interface, and finally invoking the mapped method which triggers JDBC operations, while detailing caching and executor mechanisms.
1. Obtain Configuration File Stream
The process starts by reading the MyBatis XML configuration as an InputStream :
InputStream input = Resources.getResourceAsStream("SqlSessionConfig.xml");2. Build SqlSessionFactory
The XML is parsed by XMLConfigBuilder , which creates an SqlSessionFactory using the Builder pattern.
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(input);Inside SqlSessionFactoryBuilder , the build(InputStream) method delegates to SqlSessionFactoryBuilder.build(Configuration) , returning a DefaultSqlSessionFactory .
3. Create SqlSession
From the factory, a session is opened:
SqlSession sqlSession = sessionFactory.openSession();The DefaultSqlSessionFactory creates a transaction, an executor, and finally a DefaultSqlSession instance.
4. Generate Mapper Proxy
The session creates a dynamic proxy for the mapper interface:
TestMapperDao mapper = sqlSession.getMapper(TestMapperDao.class);The proxy is built by MapperProxyFactory , which stores a MapperProxy that implements InvocationHandler . The proxy is cached in MapperRegistry.knownMappers .
5. Invoke Mapped Method
Calling a mapper method (e.g., selectByPrimaryKey(1) ) triggers the proxy’s invoke method, which retrieves a MapperMethod and calls its execute method.
System.out.println(mapper.selectByPrimaryKey(1));MapperMethod.execute determines the SQL command type (SELECT, INSERT, UPDATE, DELETE) and delegates to the appropriate SqlSession method. For a SELECT, it eventually calls DefaultSqlSession.selectOne , which uses the executor chain.
Executor Chain
The executor hierarchy consists of CachingExecutor (second‑level cache) wrapping a concrete executor such as SimpleExecutor . The caching executor builds a CacheKey , checks the second‑level cache, and falls back to the delegate executor.
public
List
query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
// ... cache lookup ...
return delegate.query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}The delegate ( SimpleExecutor ) prepares a PreparedStatement via a StatementHandler and executes it:
Statement stmt = null;
try {
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}The PreparedStatementHandler finally calls ps.execute() and hands the ResultSet to a ResultSetHandler to build the result objects.
Cache Interaction
Before querying, the executor checks the second‑level cache; if a miss occurs, the result is stored in the local (first‑level) cache and then placed into the second‑level cache after the database call completes.
6. Mapper Registration
During XML parsing, each <mapper> node registers its interface in Configuration via MapperRegistry.addMapper . This adds a MapperProxyFactory to knownMappers , enabling the sqlSession.getMapper call to retrieve the proxy.
The article also notes that the same registration works for annotation‑based mappers, where MapperAnnotationBuilder parses @Select, @Insert, etc., and registers the mapper in the same way.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
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.