沉默是金,总会发光
大家好,我是沉默
最近有粉丝私信我:“面试官上来就问 MyBatis 的四大核心组件,我脑子一片空白,最后只能尴尬说自己主要写业务代码…”
听着是不是有点耳熟?
其实不只是你,很多程序员都对 MyBatis 的底层机制“只闻其声、不见其形”。
今天就带大家把这四大组件——Executor、StatementHandler、ParameterHandler、ResultSetHandler——的职责、原理和关键流程彻底捋一遍,附上精炼示例,帮你在面试或项目调优中脱颖而出。
-01-
MyBatis 四大组件职责
┌───────────────────────────────────────┐
│ Executor │ ← 事务 & 缓存管理,调度执行
│ ┌───────────┬───────────┬──────────┐│
│ │ │ │ ││
│ │ StatementHandler ─────┐ ││
│ │ (建 stmt / 执行 SQL) │ ││
│ └───────────┬───────────┘ ││
│ │ ││
│ ParameterHandler ││
│ (填充参数) ││
│ ││
│ ResultSetHandler ││
│ (映射结果) ││
└───────────────────────────────────────┘
-02-
MyBatis 四大组件原理和关键流程
一、Executor:老板
- 核心职责
- 调度 SQL 执行
- 事务提交/回滚
- 一级缓存/二级缓存 管理
- 主要实现
SimpleExecutor
:每次都 new 一个Statement
,适合短命查询ReuseExecutor
:重用相同 SQL 的Statement
,减少重复创建BatchExecutor
:批量提交,适合大批量写入CachingExecutor
:二级缓存代理,内部持有真实 Executor执行流程(摘自 SimpleExecutor#doQuery)
// 1. 构造 StatementHandler(可被插件拦截)
StatementHandler handler = configuration.newStatementHandler(executor, ms, param, rowBounds, resultHandler, boundSql);
// 2. 准备 JDBC Statement
Statement stmt = handler.prepare(connection, transactionTimeout);
// 3. 参数绑定
handler.parameterize(stmt);
// 4. 真正执行并返回结果
return handler.query(stmt, resultHandler);
二、StatementHandler:部门经理
- 核心职责
prepare()
→ 根据 SQL 类型(简单/预编译/存储过程)创建对应Statement
parameterize()
→ 委派给ParameterHandler
绑定参数query()
/update()
→ 调用 JDBC 执行,委托ResultSetHandler
处理结果
- 常用实现
RoutingStatementHandler
:根据 SQL 类型路由到具体 HandlerSimpleStatementHandler
:执行无参静态 SQLPreparedStatementHandler
:执行带#{}
参数的预编译 SQLCallableStatementHandler
:执行存储过程示例:PreparedStatementHandler.query
@Override
public <E> List<E> query(Statement stmt, ResultHandler resultHandler) throws SQLException {PreparedStatement ps = (PreparedStatement) stmt;ps.execute(); // 执行 SQLreturn resultSetHandler.handleResultSets(ps); // 委派结果映射
}
三、ParameterHandler:翻译官
- 核心职责
将 Java 方法入参,转换并填充到 SQL 中的 “?” 占位符。 - 默认实现:
DefaultParameterHandler
@Override
public void setParameters(PreparedStatement ps) throws SQLException {List<ParameterMapping> mappings = boundSql.getParameterMappings();for (int i = 0; i < mappings.size(); i++) {ParameterMapping pm = mappings.get(i);Object value = /* 从 parameterObject 或 additionalParameter 拿到值 */;TypeHandler th = pm.getTypeHandler();th.setParameter(ps, i + 1, value, pm.getJdbcType());}
}
- TypeHandler(类型处理器)
BaseTypeHandler
提供setParameter
框架,交由子类实现setNonNullParameter
- 常见子类:
StringTypeHandler
、DoubleTypeHandler
、DateTypeHandler...
四、ResultSetHandler:讲解员
- 核心职责
将 JDBCResultSet
按照映射规则,构造成 Java 对象或集合。 - 默认实现:
DefaultResultSetHandler
private <E> List<E> handleResultSets(Statement stmt) throws SQLException {ResultSet rs = stmt.getResultSet();List<E> results = new ArrayList<>();while (rs.next()) {// 1. 构造目标对象(通过反射/构造函数)Object row = createResultObject(rs, resultMap);// 2. 按列映射属性并填充applyPropertyMappings(rs, row, resultMap);results.add((E) row);}return results;
}
- ResultHandler 与 ResultSetHandler
ResultSetHandler
负责“整批”读取并 map 出对象ResultHandler
(如DefaultResultHandler
)负责“逐条”消费,灵活自定义
-03-
简单案例
单表查询全流程示意
// 1. 用户调用 Mapper 接口
List<User> users = userMapper.selectAll();
// 2. Executor#doQuery 调度
StatementHandler sh = config.newStatementHandler(…);
PreparedStatement ps = sh.prepare(conn, timeout);
sh.parameterize(ps);
// 3. JDBC 执行 & ResultSetHandler 映射
ps.execute();
List<User> list = sh.<User>query(ps, resultHandler);
// 4. Executor 返回用户
return list;
-04-
总结
- Executor:全局调度者,掌控事务与缓存
- StatementHandler:部门经理,管控 SQL 执行链路
- ParameterHandler:翻译官,负责入参→JDBC
- ResultSetHandler:讲解员,ResultSet→Java
掌握这四大组件的职责和协作原理,不仅能帮你在面试中游刃有余,也能为项目性能调优打下扎实基础。
-05-
粉丝福利
我这里创建一个程序员成长&副业交流群,
和一群志同道合的小伙伴,一起聚焦自身发展,
可以聊:
技术成长与职业规划,分享路线图、面试经验和效率工具,
探讨多种副业变现路径,从写作课程到私活接单,
主题活动、打卡挑战和项目组队,让志同道合的伙伴互帮互助、共同进步。
如果你对这个特别的群,感兴趣的,
可以加一下,微信通过后会拉你入群,
但是任何人在群里打任何广告,都会被我T掉。