Reading the MyBatis and MyBatis-Plus Source Code: From SqlSession to the Plugin Chain
Baseline: MyBatis 3.5.x, MyBatis-Plus 3.5.x, Spring Boot 3, Java 17+.
1. The core execution chain
Mapper proxy -> SqlSession -> Executor -> StatementHandler -> JDBC -> ResultSetHandler
SqlSession is the entry point. The Executor handles queries, updates, transactions, and the first-level cache; the StatementHandler binds parameters and prepares Statements; and the ResultSetHandler maps results. MyBatis-Plus adds BaseMapper, Wrapper, automatic field filling, logical deletion, pagination, and interceptors, but does not alter JDBC transaction constraints.
2. Parameter binding
<select id="findByStatus" resultType="Order">
select * from orders where status = #{status}
</select>
String substitution is only appropriate for allowlisted table names, column names, and sorting fields; it must never be used to concatenate user input directly into SQL.
3. Executor and caching
SimpleExecutor creates a new Statement each time; ReuseExecutor reuses Statements; BatchExecutor sends updates in batches; and CachingExecutor handles the namespace-scoped second-level cache. The first-level cache lives within the SqlSession/Executor lifecycle. The second-level cache involves serialization and consistency during invalidation, so it should not be treated as a Redis cache by default.
4. The plugin chain
Pagination, optimistic locking, multi-tenancy, and data permissions are implemented through the plugin chain. Plugin ordering, tenant conditions, pagination, and logical deletion must be verified with integration tests. Logical deletion does not mean that the data stops growing. When upgrading, rely on the source code for the pinned version.