MyBatis XMLMapperBuilder 是如何解析 SQL 映射文件的? 它读取了哪些信息?

XMLMapperBuilder 是 MyBatis 中负责解析 SQL 映射 XML 文件 的关键组件。 SQL 映射文件定义了 SQL 语句、参数映射、结果映射、缓存配置等信息,用于将 Java 方法调用映射到具体的 SQL 操作。 XMLMapperBuilder 的主要职责就是读取这些 XML 文件,解析其中的 SQL 映射配置,并将这些配置信息存储到 Configuration 对象中,供 MyBatis 运行时使用。

1. XMLMapperBuilder 如何解析 SQL 映射文件:

XMLMapperBuilder 的解析过程与 XMLConfigBuilder 类似,也主要依赖于 XPath 技术来定位和提取 XML 文件中的数据。 以下是 XMLMapperBuilder 解析 SQL 映射文件的详细步骤:

  • 1.1. 初始化 XMLMapperBuilder:

    XMLConfigBuilder 解析 <mappers> 元素时,如果 <mapper> 子元素指定了 resourceurl 属性 (指向 XML Mapper 文件),XMLConfigBuilder 会为每个 XML Mapper 文件创建一个 XMLMapperBuilder 实例,并将 Mapper XML 文件的 InputStreamReader 传递给它。

    java 复制代码
    // 在 XMLConfigBuilder 中,解析 <mapper resource="..."> 或 <mapper url="..."> 时会创建 XMLMapperBuilder
    XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource);
    • inputStreamReader: 用于读取 Mapper XML 文件的输入流或字符流。
    • configuration: XMLConfigBuilder 正在构建的 Configuration 对象。 XMLMapperBuilder 需要访问 Configuration 对象,以便将解析到的 Mapper 映射信息注册到 Configuration 中。
    • resource: Mapper XML 文件的资源路径 (例如 com/example/mapper/UserMapper.xml),用于日志记录和错误提示。
  • 1.2. 调用 XMLMapperBuilder.parse() 方法:

    XMLMapperBuilder 的核心解析方法也是 parse()。 调用 parse() 方法开始 SQL 映射文件的解析过程.

    java 复制代码
    mapperParser.parse();
  • 1.3. 使用 XPath 解析 XML 元素:

    XMLMapperBuilder.parse() 方法内部会使用 XPath 表达式 来定位和读取 Mapper XML 文件中的各个元素。 XPath 帮助解析器高效地访问和提取 XML 结构中的特定元素和属性。

    例如,要解析 <select> 元素,XMLMapperBuilder 可能会使用 XPath 表达式类似于 "mapper/select" 来定位 <select> 元素。

  • 1.4. 顺序解析 XML 元素 :

    XMLMapperBuilder 会按照一定的顺序解析 Mapper XML 文件中的元素,大致顺序如下 (与 Mapper XML 文件中元素的建议顺序一致):

    • <mapper> (根元素): 首先解析根元素 <mapper>,作为整个 Mapper 映射文件的入口。
    • <cache-ref>: 解析 <cache-ref> 元素,引用其他 Mapper 的缓存配置。
    • <cache>: 解析 <cache> 元素,配置 Mapper 级别的缓存。
    • <resultMap>: 解析 <resultMap> 元素,定义结果集映射。
    • <parameterMap> (已过时): 解析 <parameterMap> 元素 (已过时,不推荐使用,通常使用内联参数映射)。
    • <sql>: 解析 <sql> 元素,定义可重用的 SQL 片段。
    • <select>, <insert>, <update>, <delete>: 解析 <select>, <insert>, <update>, <delete> 元素,定义 SQL 查询、插入、更新、删除语句。
  • 1.5. 构建 MappedStatement 对象并注册到 Configuration:

    对于每个解析到的 <select>, <insert>, <update>, <delete> 元素,XMLMapperBuilder 会根据 XML 元素的内容,构建一个 MappedStatement 对象MappedStatement 对象封装了 SQL 语句的所有相关信息,例如:

    • SQL 语句文本 (经过动态 SQL 处理)。
    • SQL 语句类型 (SELECT, INSERT, UPDATE, DELETE)。
    • 参数类型 (parameterType)。
    • 结果类型或结果映射 (resultType, resultMap)。
    • 缓存配置 (useCache, flushCache)。
    • 超时时间 (timeout)。
    • Statement 类型 (STATEMENT, PREPARED, CALLABLE)。
    • FetchSize, ResultSetType, 等其他 JDBC 相关配置。

    构建好 MappedStatement 对象后,XMLMapperBuilder 会将其 注册到 Configuration 对象的 mapperRegistry 属性 (一个 MapperRegistry 对象) 中 。 注册时,会使用 Mapper 接口的全限定名 + SQL 语句的 id 属性作为 MappedStatement 的唯一 ID (mappedStatementId)。 例如,如果 Mapper 接口是 com.example.mapper.UserMapper<select id="getUserById"> 语句的 mappedStatementId 将是 com.example.mapper.UserMapper.getUserById

  • 1.6. 注册 Mapper 接口到 Configuration (如果 Mapper XML 文件关联了 Mapper 接口):

    如果 Mapper XML 文件的 <mapper namespace="..."> 元素指定了 Mapper 接口的命名空间 (namespace),XMLMapperBuilder 还会将对应的 Mapper 接口注册到 Configuration 对象的 mapperRegistry 中。 这样,MyBatis 才能在运行时根据 Mapper 接口找到对应的 SQL 映射配置。

  • 1.7. 完成解析:

    XMLMapperBuilder.parse() 方法完成 SQL 映射文件的解析和注册后,解析过程结束。

2. XMLMapperBuilder 读取了哪些信息 (XML 元素及其含义):

XMLMapperBuilder 主要读取和解析 SQL 映射 XML 文件中的以下信息:

  • <mapper>: 根元素,定义 Mapper 映射文件的命名空间 (namespace)。

    • 读取信息:
      • namespace 属性:Mapper 接口的命名空间 (全限定名)。
    • 存储到 Configuration 对象: 用于确定 Mapper 接口和 SQL 映射之间的关联关系,以及构建 MappedStatement 的 ID。
  • <cache-ref>:

    • 作用: 引用其他 Mapper 的缓存配置,实现缓存共享。
    • 读取信息:
      • namespace 属性:被引用的 Mapper 的命名空间。
    • 存储到 Configuration 对象: 将缓存引用信息存储到当前 Mapper 的 cache 属性 (一个 Cache 对象) 中,指向被引用 Mapper 的缓存。
  • <cache>:

    • 作用: 配置 Mapper 级别的缓存,用于提高查询性能。
    • 读取信息:
      • type 属性 (可选):缓存实现类型 (例如 PERPETUAL, LRU, FIFO, WEAK, SOFT, 或自定义缓存实现类)。 默认 PERPETUAL
      • eviction 属性 (可选):缓存回收策略 (例如 LRU, FIFO, WEAK, SOFT)。 默认 LRU
      • flushInterval 属性 (可选):缓存刷新间隔 (毫秒)。
      • size 属性 (可选):缓存大小 (对象个数)。
      • readOnly 属性 (可选):是否只读缓存 (true/false)。 默认 false
      • blocking 属性 (可选):是否阻塞缓存 (true/false)。 默认 false
      • <property> 子元素 (可选):缓存实现类的自定义属性。
    • 存储到 Configuration 对象: 根据配置信息创建 Cache 接口的实现类实例,并将其设置到当前 Mapper 的 cache 属性 (一个 Cache 对象) 中。
  • <resultMap>:

    • 作用: 定义复杂的结果集映射规则,用于将查询结果列映射到 Java 对象属性。
    • 读取信息:
      • id 属性:resultMap 的唯一 ID。
      • type 属性:结果映射的目标 Java 类型。
      • extends 属性 (可选):继承自其他 resultMap
      • autoMapping 属性 (可选):是否开启自动映射 (true/false, partial/full, 默认 true)。
      • <constructor> 子元素 (可选):配置构造器注入。
      • <id> 子元素:配置主键映射。
      • <result> 子元素:配置普通属性映射。
      • <association> 子元素:配置关联对象映射 (一对一)。
      • <collection> 子元素:配置集合属性映射 (一对多)。
      • <discriminator> 子元素:配置鉴别器映射 (用于多态映射)。
    • 存储到 Configuration 对象: 根据配置信息创建 ResultMap 对象,并将其注册到 Configuration 对象的 resultMapRegistry 属性 (一个 ResultMapRegistry 对象) 中,使用 resultMapid 作为 key。
  • <parameterMap> (已过时):

    • 作用: 已过时的参数映射配置方式,不推荐使用,通常使用内联参数映射 (#{}${})。
    • 读取信息:
      • id 属性:parameterMap 的 ID。
      • type 属性:参数类型。
      • <parameter> 子元素:配置参数映射。
    • 存储到 Configuration 对象: 如果存在 <parameterMap>,会创建 ParameterMap 对象并注册到 Configuration 对象的 parameterMapRegistry 属性 (一个 ParameterMapRegistry 对象) 中,使用 parameterMapid 作为 key。 但通常不推荐使用 parameterMap,现代 MyBatis 开发中几乎不用。
  • <sql>:

    • 作用: 定义可重用的 SQL 片段,可以在多个 SQL 语句中引用,提高 SQL 复用性。
    • 读取信息:
      • id 属性:sql 片段的唯一 ID。
      • SQL 语句内容 (CDATA 或普通文本)。
    • 存储到 Configuration 对象:<sql> 元素定义的 SQL 片段 (SqlNode 对象) 存储到 Configuration 对象的 sqlFragments 属性 (一个 Map<String, XNode>) 中,使用 sql 片段的 id 作为 key。
  • <select>, <insert>, <update>, <delete>:

    • 作用: 定义 SQL 查询、插入、更新、删除语句,并将 Java 方法与 SQL 语句关联起来。

    • 读取信息 (通用属性):

      • id 属性:SQL 语句的唯一 ID (在 Mapper 命名空间内唯一)。
      • parameterType 属性 (可选):参数类型。
      • parameterMap 属性 (可选, 已过时):参数映射引用 (不推荐使用)。
      • resultType 属性 (可选):结果类型。
      • resultMap 属性 (可选):结果映射引用。
      • flushCache 属性 (可选):是否刷新缓存 (true/false)。 默认值取决于 SQL 类型 (SELECT: false, 其他: true)。
      • useCache 属性 (可选, 仅 <select> 有效):是否使用二级缓存 (true/false)。 默认 true
      • timeout 属性 (可选):超时时间 (秒)。
      • fetchSize 属性 (可选):JDBC Fetch Size。
      • statementType 属性 (可选):Statement 类型 (STATEMENT, PREPARED, CALLABLE)。 默认 PREPARED
      • resultSetType 属性 (可选):ResultSet 类型 (FORWARD_ONLY, SCROLL_SENSITIVE, SCROLL_INSENSITIVE)。
      • databaseId 属性 (可选):数据库 ID,用于多数据库支持。
      • lang 属性 (可选):语言驱动器 (例如 XML, RAW, 默认 XML)。
      • SQL 语句内容 (CDATA 或普通文本,可以包含动态 SQL 标签)。
    • 读取信息 (<select>):

      • keyProperty 属性 (可选):用于指定主键属性,用于缓存管理。
      • keyColumn 属性 (可选):用于指定主键列名,用于缓存管理。
      • resultOrdered 属性 (可选):结果是否排序 (true/false)。 默认 false
      • resultSetType 属性 (可选):ResultSet 类型 (FORWARD_ONLY, SCROLL_SENSITIVE, SCROLL_INSENSITIVE)。
      • cursorName 属性 (可选):游标名称 (用于存储过程)。
    • 读取信息 (<insert>, <update>, <delete>):

      • keyGenerator 属性 (可选, <insert> 有效):主键生成器类型 (例如 JDBC, SELECT KEY, CUSTOM)。
      • keyProperty 属性 (可选, <insert> 有效):主键属性名 (用于获取生成的主键值)。
      • keyColumn 属性 (可选, <insert> 有效):主键列名 (用于获取生成的主键值)。
      • useGeneratedKeys 属性 (可选, <insert> 有效):是否使用 JDBC 的 getGeneratedKeys 获取主键 (true/false)。 默认 false
      • parameterType 属性 (可选, <update>, <delete> 可以省略,从方法签名推断)。
    • 存储到 Configuration 对象: 对于每个 <select>, <insert>, <update>, <delete> 元素,XMLMapperBuilder 会根据解析到的信息,创建一个 MappedStatement 对象,并将其注册到 Configuration 对象的 mappedStatements 属性 (一个 StrictMap<MappedStatement>) 中,使用 Mapper 命名空间 + SQL 语句 ID 作为 key。

总结:

XMLMapperBuilder 是 MyBatis SQL 映射文件的解析引擎。 它使用 XPath 技术高效地解析 Mapper XML 文件,读取 SQL 语句、参数映射、结果映射、缓存配置等信息,并将这些信息封装在 MappedStatement, ResultMap, Cache 等对象中。 最终,这些对象会被注册到 Configuration 对象中,构成 MyBatis 运行时 SQL 映射配置的核心部分。

相关推荐
麦聪聊数据41 分钟前
为何通用堡垒机无法在数据库运维中实现精准风控?
数据库·sql·安全·低代码·架构
枷锁—sha2 小时前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全
独断万古他化4 小时前
【SSM开发实战:博客系统】(三)核心业务功能开发与安全加密实现
spring boot·spring·mybatis·博客系统·加密
怣505 小时前
MySQL多表连接:全外连接、交叉连接与结果集合并详解
数据库·sql
证榜样呀7 小时前
2026 中专大数据技术专业可考的证书有哪些,必看!
大数据·sql
Codefengfeng7 小时前
数据安全知识点速通
sql
fengxin_rou8 小时前
[Redis从零到精通|第四篇]:缓存穿透、雪崩、击穿
java·redis·缓存·mybatis·idea·多线程
逍遥德9 小时前
Sring事务详解之02.如何使用编程式事务?
java·服务器·数据库·后端·sql·spring
驾数者9 小时前
Flink SQL实时数仓实战:基于Flink SQL的完整项目案例
sql·flink·linq