mappedstatement是mybatis封装sql映射语句元数据的核心不可变对象,包含唯一id(namespace.methodname)、sqlsource、parametermap、resultmaps、fetchsize、timeout、usecache等执行所需全部结构化信息,并通过builder模式构建,供executor等组件复用。

MappedStatement 是 MyBatis 中封装 SQL 元数据的核心对象,它不直接执行 SQL,而是把一条映射语句(比如 <select id="getUserById"></select>)的全部结构化信息“装进”一个不可变实例里,供后续执行链(如 Executor、StatementHandler)按需读取和使用。
它封装了哪些关键元数据
MappedStatement 并非简单存个 SQL 字符串,而是分层组织了从配置到行为的完整描述:
-
ID 与定位信息:唯一标识符
id(格式为namespace.methodName,如com.example.UserMapper.getUserById),配合resource(指向 mapper.xml 文件路径)确保能准确定位到原始定义位置 -
SQL 内容载体:持有
SqlSource对象,而非原始字符串;SqlSource负责在运行时根据参数动态生成最终可执行的 SQL(支持 #{}、${}、等动态逻辑) -
参数与结果契约:通过
ParameterMap描述入参如何绑定到 PreparedStatement(如类型转换、属性提取);通过resultMaps列表定义结果集如何映射成 Java 对象(支持resultType简单类型或resultMap复杂嵌套) -
执行控制参数:包括
fetchSize(JDBC 一次拉取行数)、timeout(超时秒数)、statementType(STATEMENT / PREPARED / CALLABLE)、resultSetType(FORWARD_ONLY / SCROLL_SENSITIVE 等) -
缓存与行为标记:
useCache、flushCacheRequired、resultOrdered等布尔字段,直接影响二级缓存是否启用、是否清空缓存、结果是否有序等语义
Builder 模式构建过程体现封装逻辑
MappedStatement 使用静态内部类 Builder 构造,强制所有字段在初始化阶段显式设置,避免状态不一致。典型构建流程如下:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 解析 XML 时,XMLMapperBuilder 读取
<select></select>标签的id、parameterType、resultType等属性 - 将
#{id}解析为ParameterMapping列表,构造成ParameterMap,再注入 Builder - 将 SQL 文本包装为
DynamicSqlSource或RawSqlSource,传入 Builder - 根据
resultType自动推导出默认ResultMap,或根据resultMap属性引用已注册的ResultMap对象 - 调用
build()方法完成不可变实例创建,此后所有字段只读
为什么需要封装成对象而不是散放配置
因为 MyBatis 的执行是“一次解析、多次复用”模型:
- SQL 解析、参数映射规则、结果映射规则都属高开销操作,只在启动或首次调用时做一次,之后全靠 MappedStatement 缓存的元数据驱动
- Executor 执行时,只需传入
mappedStatement和参数对象,无需再解析 XML 或重新推导类型——所有映射逻辑已预置在对象内部 - 不同 Executor(Simple/Reuse/Batch)或 StatementHandler(Routing/PreparedStatement)共享同一份 MappedStatement,实现关注点分离
它和 Mapper 接口方法怎么对应上
Mapper 接口本身无实现,MyBatis 用 JDK 动态代理生成代理对象。当调用 userMapper.getUserById(123) 时:
- 代理拦截该方法,提取接口全限定名 + 方法名,拼出标准 ID:
com.example.UserMapper.getUserById - 从 Configuration 的
mappedStatementsMap 中,以该 ID 为 key 查出对应的 MappedStatement 实例 - 将方法参数作为入参对象传给 Executor,Executor 再委托给 StatementHandler,全程依赖 MappedStatement 提供的元数据完成参数设置、SQL 执行、结果映射
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










