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>子元素指定了resource或url属性 (指向 XML Mapper 文件),XMLConfigBuilder会为每个 XML Mapper 文件创建一个XMLMapperBuilder实例,并将 Mapper XML 文件的InputStream或Reader传递给它。// 在 XMLConfigBuilder 中,解析 <mapper resource="..."> 或 <mapper url="..."> 时会创建 XMLMapperBuilder XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource);inputStream或Reader: 用于读取 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 映射文件的解析过程.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对象) 中,使用resultMap的id作为 key。
-
<parameterMap>(已过时):- 作用: 已过时的参数映射配置方式,不推荐使用,通常使用内联参数映射 (
#{}或${})。 - 读取信息:
id属性:parameterMap的 ID。type属性:参数类型。<parameter>子元素:配置参数映射。
- 存储到
Configuration对象: 如果存在<parameterMap>,会创建ParameterMap对象并注册到Configuration对象的parameterMapRegistry属性 (一个ParameterMapRegistry对象) 中,使用parameterMap的id作为 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 映射配置的核心部分。
