沉默是金,总会发光
大家好,我是沉默
最近有粉丝私信我:"面试官上来就问 MyBatis 的四大核心组件,我脑子一片空白,最后只能尴尬说自己主要写业务代码..."
听着是不是有点耳熟?
其实不只是你,很多程序员都对 MyBatis 的底层机制"只闻其声、不见其形"。
今天就带大家把这四大组件------Executor、StatementHandler、ParameterHandler、ResultSetHandler------的职责、原理和关键流程彻底捋一遍,附上精炼示例,帮你在面试或项目调优中脱颖而出。
**-**01-
MyBatis 四大组件职责
scss
┌───────────────────────────────────────┐│ Executor │ ← 事务 & 缓存管理,调度执行│ ┌───────────┬───────────┬──────────┐││ │ │ │ │││ │ StatementHandler ─────┐ │││ │ (建 stmt / 执行 SQL) │ │││ └───────────┬───────────┘ │││ │ │││ ParameterHandler │││ (填充参数) │││ │││ ResultSetHandler │││ (映射结果) ││└───────────────────────────────────────┘
- 02-
MyBatis 四大组件原理和关键流程
一、Executor:老板
-
核心职责
-
- 调度 SQL 执行
- 事务提交/回滚
- 一级缓存/二级缓存 管理
-
主要实现
-
SimpleExecutor
:每次都 new 一个Statement
,适合短命查询ReuseExecutor
:重用相同 SQL 的Statement
,减少重复创建BatchExecutor
:批量提交,适合大批量写入CachingExecutor
:二级缓存代理,内部持有真实 Executor
-
执行流程(摘自 SimpleExecutor#doQuery)
perl
// 1. 构造 StatementHandler(可被插件拦截)StatementHandler handler = configuration.newStatementHandler( executor, ms, param, rowBounds, resultHandler, boundSql);// 2. 准备 JDBC StatementStatement 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
java
@Overridepublic <E> List<E> query(Statement stmt, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) stmt; ps.execute(); // 执行 SQL return resultSetHandler.handleResultSets(ps); // 委派结果映射}
三、ParameterHandler:翻译官
-
核心职责
将 Java 方法入参,转换并填充到 SQL 中的 "?" 占位符。
-
默认实现 :
DefaultParameterHandler
css
@Overridepublic 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
java
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-
简单案例
单表查询全流程示意
sql
// 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-**粉丝福利
r
我这里创建一个程序员成长&副业交流群,
和一群志同道合的小伙伴,一起聚焦自身发展,
可以聊:
技术成长与职业规划,分享路线图、面试经验和效率工具,
探讨多种副业变现路径,从写作课程到私活接单,
主题活动、打卡挑战和项目组队,让志同道合的伙伴互帮互助、共同进步。
如果你对这个特别的群,感兴趣的,
可以加一下, 微信通过后会拉你入群,
但是任何人在群里打任何广告,都会被我T掉。