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
传递给它。java// 在 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 映射文件的解析过程.javamapperParser.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 映射配置的核心部分。