你是否曾好奇:当你调用MyBatis的selectOne()方法时,你的SQL语句究竟经历了怎样的旅程才最终到达数据库?本文将深入MyBatis内核,揭示从SqlSession到JDBC的完整执行链路,让你彻底掌握MyBatis的核心工作原理。
一、执行链路全景图
在深入源码前,先看整体执行流程:
SqlSession -> Executor -> StatementHandler -> ParameterHandler -> JDBC Statement -> ResultSetHandler二、SqlSession:入口门户
SqlSession是MyBatis的核心接口,所有数据库操作都从这里开始。以DefaultSqlSession为例:
// DefaultSqlSession.java
public <E> List<E> selectList(String statement, Object parameter) {
    MappedStatement ms = configuration.getMappedStatement(statement);
    return executor.query(ms, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
}
关键点:
- 通过statement从Configuration获取MappedStatement
 - 委托给Executor执行查询
 
三、Executor:执行引擎
Executor是真正的执行者,采用典型的命令模式。以SimpleExecutor为例:
// SimpleExecutor.java
public <E> List<E> query(MappedStatement ms, Object parameter, 
                         RowBounds rowBounds, ResultHandler resultHandler) {
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}执行过程:
- 获取BoundSql(包含最终要执行的SQL和参数映射)
 - 创建缓存Key(如果启用二级缓存)
 - 执行doQuery()方法
 
四、StatementHandler:SQL语句处理器
Executor最终会调用StatementHandler:
// SimpleExecutor.doQuery()
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, 
                                  rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);PreparedStatementHandler核心处理流程:
// SimpleExecutor.doQuery()
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, 
                                  rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);PreparedStatementHandler核心处理流程:
// PreparedStatementHandler.java
public <E> List<E> query(Statement statement, ResultHandler resultHandler) {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    return resultSetHandler.handleResultSets(ps);
}五、ParameterHandler:参数处理专家
参数处理发生在StatementHandler初始化时:
// DefaultParameterHandler.java
public void setParameters(PreparedStatement ps) {
    for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        Object value;
        // 复杂参数处理逻辑...
        TypeHandler typeHandler = parameterMapping.getTypeHandler();
        typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
    }
}六、JDBC交互:最后的桥梁
MyBatis最终通过标准的JDBC API与数据库交互:
// PreparedStatementHandler.execute()
public int update(Statement statement) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    return ps.getUpdateCount();
}七、ResultSetHandler:结果集转换大师
结果集处理是最复杂的部分:
// DefaultResultSetHandler.java
public List<Object> handleResultSets(Statement stmt) throws SQLException {
    final List<Object> multipleResults = new ArrayList<>();
    ResultSet rs = stmt.getResultSet();
    while (rs != null) {
        // 处理单结果集
        Object result = getSingleResult(rs);
        multipleResults.add(result);
        // 处理多结果集
        if (stmt.getMoreResults()) {
            rs = stmt.getResultSet();
        } else {
            rs = null;
        }
    }
    return collapseSingleResultList(multipleResults);
}八、设计模式应用
MyBatis执行链路中巧妙运用了多种设计模式:
- 门面模式:SqlSession作为统一入口
 - 责任链模式:插件拦截器实现
 - 模板方法模式:BaseExecutor定义执行骨架
 - 装饰器模式:CachingExecutor包装普通Executor
 
九、性能优化关键点
- Statement重用:ReuseExecutor会缓存PreparedStatement
 - 批量处理:BatchExecutor优化批量操作
 - 延迟加载:通过Proxy实现关联对象的延迟加载
 - 缓存机制:一级缓存(Session级别)和二级缓存(Mapper级别)
 
十、插件扩展原理
MyBatis通过动态代理实现插件机制:
// Plugin.java
public static Object wrap(Object target, Interceptor interceptor) {
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
    Class<?> type = target.getClass();
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
        return Proxy.newProxyInstance(
            type.getClassLoader(),
            interfaces,
            new Plugin(target, interceptor, signatureMap));
    }
    return target;
}结语
通过本文的源码级分析,你应该已经掌握了MyBatis从SqlSession到JDBC的完整执行链路。理解这些底层原理不仅能帮助你在遇到问题时快速定位,更能让你在复杂业务场景下做出更合理的设计决策。下次当你使用MyBatis时,不妨在脑海中回想这个执行流程,相信你会对它有全新的认识。
