MappedStatement 是 MyBatis 中封装 SQL 映射元数据的不可变蓝图,包含唯一标识、SQL 类型、SqlSource、参数映射、ResultMap、缓存配置等静态信息,由 XML 或注解解析构建并缓存在 Configuration 中。

MappedStatement 是 MyBatis 中封装一条 SQL 映射定义的核心对象,它不直接包含执行时的参数或结果,而是**静态描述**“这条 SQL 怎么来、怎么用、怎么处理”。它由 XML 或注解配置解析而来,在 SqlSession 初始化阶段就构建完成,并被缓存在 Configuration 中。
封装了哪些关键 SQL 映射信息?
一个 MappedStatement 实际上是 SQL 元数据的“蓝图”,主要包含以下维度:
-
唯一标识:namespace + id(如
com.example.UserMapper.selectById),用于在 Configuration 中全局定位 - SQL 类型:INSERT / UPDATE / DELETE / SELECT / FLUSH,决定执行器行为和返回值处理逻辑
- 绑定的 SQL 源:SqlSource 对象(可能是 StaticSqlSource、DynamicSqlSource 等),负责在运行时根据参数生成最终可执行的 BoundSql
- 参数映射:ParameterMap(已较少用)或直接通过 @Param 注解/方法签名推导,明确入参类型、名称与占位符的对应关系
- 结果映射:ResultMap(核心!),定义结果集如何映射为 Java 对象(字段名→属性名、嵌套查询、鉴别器、自动映射策略等)
- 缓存配置:是否启用二级缓存、flushCache 设置、useCache 控制等
- 超时与获取行数:timeout、fetchSize,影响 Statement 执行行为
-
语句日志级别:通过
statementType(STATEMENT / PREPARED / CALLABLE)和日志插件配合控制
它是怎么被创建出来的?
MappedStatement 不是手动 new 的,而是由 XMLMapperBuilder(解析 <mapper>)或 AnnotationMapperParser(解析 @Select 等)在启动时构建:
- 读取 <select id="xxx" resultType="User">SELECT * FROM user WHERE id = #{id}</select>
- 解析 id、parameterType(可选)、resultType/resultMap、SQL 文本等
- 将 SQL 文本包装成 SqlSource(含 ${} 和 #{} 的解析逻辑)
- 根据 resultType 自动构建 ResultMap,或引用已定义的 resultMap
- 组装成 Builder,调用
builder.build()得到不可变的 MappedStatement 实例
它和 BoundSql 有什么区别?
这是关键区分点:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- MappedStatement 是“模板”:只存映射规则,不依赖具体参数,线程安全,复用多次
-
BoundSql 是“快照”:每次执行时,MappedStatement 调用
sqlSource.getBoundSql(parameter)生成,含真实 SQL 字符串、参数映射关系(ParameterMappings)、实参(parameterObject)等,是单次执行的上下文
例如:同一 MappedStatement selectById,传入 id=1 和 id=100 时,会生成两个不同的 BoundSql,但共享同一个 MappedStatement。
你可以安全地从中获取什么?
在自定义插件(Interceptor)或调试中,常通过 MappedStatement 获取元信息:
-
ms.getId()→ 获取全限定方法名 -
ms.getSqlCommandType()→ 判断是查询还是修改 -
ms.getBoundSql(param).getSql()→ 获取当前参数下生成的真实 SQL(注意:需先有参数) -
ms.getResultMap().getId()→ 查看用了哪个 resultMap -
ms.getConfiguration().getMappedStatement(id)→ 反向查其他语句(慎用循环引用)
但不要试图修改它的字段——它是不可变的(final 修饰关键属性),所有 builder 阶段完成后即冻结。

















