MyBatis 的 SQL 执行过程可以分为 6 个核心阶段,我们将通过源码逐层分析:
当调用 SqlSession.getMapper()
时,MyBatis 通过 MapperProxyFactory
创建接口的代理对象:
// org.apache.ibatis.binding.MapperProxyFactory
public class MapperProxyFactory<T> {
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
}
// org.apache.ibatis.binding.MapperProxy
public class MapperProxy<T> implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 创建 MapperMethod 执行器
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args); // 进入核心执行流程
}
}
MapperMethod
根据方法签名选择执行策略:
// org.apache.ibatis.binding.MapperMethod
public class MapperMethod {
public Object execute(SqlSession sqlSession, Object[] args) {
switch (command.getType()) {
case INSERT:
return sqlSession.insert(command.getName(), param);
case UPDATE:
return sqlSession.update(...);
case SELECT:
if (method.returnsVoid()) {
sqlSession.select(...);
} else {
return sqlSession.selectOne(...); // 以查询为例
}
// ... DELETE 等其他操作
}
}
}
DefaultSqlSession
委托给 Executor
执行:
// org.apache.ibatis.session.defaults.DefaultSqlSession
public class DefaultSqlSession implements SqlSession {
@Override
public <T> T selectOne(String statement, Object parameter) {
List<T> list = this.selectList(statement, parameter);
if (list.size() == 1) return list.get(0);
if (list.size() > 1) throw new TooManyResultsException();
return null;
}
@Override
public <E> List<E> selectList(String statement, Object parameter) {
// 获取预编译的SQL对象
MappedStatement ms = configuration.getMappedStatement(statement);
// 委托Executor执行
return executor.query(ms, wrapCollection(parameter), RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
}
}
BaseExecutor
实现缓存和事务管理:
// org.apache.ibatis.executor.BaseExecutor
public abstract class BaseExecutor implements Executor {
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
// 1. 获取BoundSql(包含解析后的SQL和参数)
BoundSql boundSql = ms.getBoundSql(parameter);
// 2. 创建缓存Key
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
// 3. 查询数据库(核心方法)
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
private <E> List<E> queryFromDatabase(...) {
// 实际执行SQL的方法
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
// 放入本地缓存(一级缓存)
localCache.putObject(key, list);
return list;
}
}
具体执行由子类 PreparedStatementHandler
完成:
// org.apache.ibatis.executor.statement.PreparedStatementHandler
public class PreparedStatementHandler extends BaseStatementHandler {
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute(); // JDBC 执行SQL
// 结果集处理
return resultSetHandler.handleResultSets(ps);
}
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
// 关键步骤:创建 PreparedStatement
return connection.prepareStatement(sql, ...);
}
}
将 ResultSet 映射为 Java 对象:
// org.apache.ibatis.executor.resultset.DefaultResultSetHandler
public class DefaultResultSetHandler implements ResultSetHandler {
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
final List<Object> multipleResults = new ArrayList<>();
ResultSet rs = stmt.getResultSet();
// 遍历结果集
while (rs != null) {
// 获取结果映射配置
ResultMap resultMap = mappedStatement.getResultMap();
// 构建结果对象
while (rs.next()) {
Object rowValue = getRowValue(rs, resultMap);
multipleResults.add(rowValue);
}
rs = getNextResultSet(stmt);
}
return collapseSingleResultList(multipleResults);
}
private Object getRowValue(ResultSet rs, ResultMap resultMap) throws SQLException {
// 创建目标对象实例
Object resultObject = createResultObject(rs, resultMap, null);
// 应用自动映射
applyAutomaticMappings(rs, resultObject, null);
// 应用手动映射
applyPropertyMappings(rs, resultObject, ...);
return resultObject;
}
}
三层缓存机制:
MapperProxy
缓存 MapperMethodExecutor
实现一级缓存MappedStatement
支持二级缓存插件拦截点:
// 核心拦截点签名
@Intercepts({
@Signature(type=Executor.class, method="query",...),
@Signature(type=StatementHandler.class, method="prepare",...)
})
可在 SQL 执行前后插入自定义逻辑
动态 SQL 处理:
BoundSql
包含最终执行的 SQL 和参数映射:
public class BoundSql {
private String sql; // 解析后的SQL
private List<ParameterMapping> parameterMappings;
private Object parameterObject; // 原始参数
}
延迟加载:
ResultLoaderMap
通过动态代理实现关联对象的延迟加载
避免 N+1 查询:
使用
的嵌套结果映射代替多次查询
重用 Executor:
// 批量操作时使用 BatchExecutor
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
合理设置 fetchSize:
<select id="selectLargeData" fetchSize="1000">
SELECT * FROM large_table
select>
结果集流式处理:
try (SqlSession session = sqlSessionFactory.openSession()) {
try (Cursor<Order> cursor = session.selectCursor("selectOrders")) {
cursor.forEach(order -> process(order));
}
}
通过理解 MyBatis 的分层设计和核心源码实现,可以更好地进行性能调优和问题排查。