上一篇主要讲了MappedStatement基本概念,接下来主要分析动态sql语句怎么解析成MappedStatement。
在 MyBatis 中,动态 SQL 是指根据条件动态生成 SQL 语句的功能。动态 SQL 语句通常在 Mapper 文件中使用 <if>, <choose>, <when>, <otherwise>, <foreach> 等标签来实现。当 MyBatis 执行动态 SQL 时,它会将这些动态 SQL 解析成一个 MappedStatement 对象,然后通过 Executor 执行相应的 SQL。
1. 动态 SQL 的解析过程
动态 SQL 的解析主要是通过 SQL 构建器和动态 SQL 标签(如 <if>, <choose>, <when>, <foreach> 等)来实现的。MyBatis 在解析这些动态标签时,会生成相应的 SQL 语句,并将其包装成 MappedStatement 对象。
1.1. 动态 SQL 标签
在 MyBatis 的 XML 配置文件中,动态 SQL 是通过一组特定的标签来实现的。例如:
<select id="selectUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>
在上面的例子中,<if> 标签根据传入的条件来动态生成 SQL 语句。如果 name 不为空,则会生成 AND name = #{name} 部分;如果 age 不为空,则会生成 AND age = #{age} 部分。<where> 标签会根据是否有动态条件生成 WHERE 子句。
1.2. 动态 SQL 解析的关键组件
在 MyBatis 中,动态 SQL 的解析过程通常涉及以下几个步骤:
-
SQL 源 (
SqlSource) 的生成:- 在解析动态 SQL 时,MyBatis 会根据
Mapper文件中的 XML 标签生成一个SqlSource对象。SqlSource对象负责保存原始的 SQL 语句及其动态部分。它包含了 SQL 的模板(即静态部分)和动态 SQL 条件(即根据输入条件决定是否加入的部分)。
- 在解析动态 SQL 时,MyBatis 会根据
-
DynamicSqlSource:DynamicSqlSource是 MyBatis 中处理动态 SQL 的类,它会将动态部分和静态部分结合起来,动态构建最终的 SQL 语句。- 在执行 SQL 时,
DynamicSqlSource会根据输入参数的不同,动态地生成最终的 SQL 语句。
-
生成
MappedStatement:- 在
Mapper文件解析的过程中,MyBatis 会根据id、SQL 类型、参数类型、返回类型等生成一个MappedStatement。这个MappedStatement对象会包含对应的SqlSource,它负责执行 SQL 查询时生成最终的 SQL 语句。
- 在
2. 动态 SQL 解析流程
以下是 MyBatis 解析动态 SQL 并生成 MappedStatement 的主要步骤:
2.1. 解析 Mapper 文件
当 MyBatis 启动时,SqlSessionFactory 会解析 Mapper 文件中的 SQL 映射语句(<select>、<insert>、<update>、<delete>)。在解析过程中,如果遇到动态 SQL 标签(如 <if>、<choose>、<foreach> 等),MyBatis 会调用相应的解析器来处理这些标签。
2.2. 生成 SqlSource
对于动态 SQL,MyBatis 会为每个动态 SQL 语句生成一个 SqlSource 对象。SqlSource 是 MyBatis 用来构建 SQL 的接口,它的实现类有:
StaticSqlSource:用于普通静态 SQL。DynamicSqlSource:用于动态 SQL。
DynamicSqlSource 会在 SQL 执行时根据参数动态地生成最终的 SQL 语句。SqlSource 对象不仅包含了 SQL 的文本模板,还包含了如何根据输入参数动态生成 SQL 的逻辑。
2.3. 构建 MappedStatement
MappedStatement 是 MyBatis 中一个非常核心的类,它封装了与 SQL 执行相关的所有元数据(如 SQL、返回值类型、参数类型等)。MyBatis 会根据映射文件中的配置,构建一个 MappedStatement 对象。
以下是 MappedStatement 的构建过程:
MappedStatement.Builder builder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType);
builder.parameterMap(parameterMap);
builder.resultMaps(resultMaps);
MappedStatement mappedStatement = builder.build();
id:表示该映射语句的唯一标识符,通常是 SQL 语句的id属性。sqlSource:表示 SQL 源,这里会传入动态 SQL 的SqlSource。sqlCommandType:SQL 执行类型,如SELECT、INSERT、UPDATE、DELETE。parameterMap:表示 SQL 语句的参数映射,描述如何将输入参数传递到 SQL 语句中。resultMaps:表示 SQL 查询结果的映射,描述如何将查询结果转换为 Java 对象。
2.4. MappedStatement 注册到 Configuration 中
MyBatis 在解析所有 Mapper 文件时,会将生成的 MappedStatement 对象存储在 Configuration 的 mappedStatements 中,使用 SQL 语句的 id 作为键。这些 MappedStatement 对象将在 SQL 执行时被 Executor 用来执行具体的 SQL 操作。
2.5. 执行 SQL
在 Executor 执行 SQL 时,MappedStatement 会被检索到,并且通过 SqlSource 动态生成最终的 SQL 语句。Executor 根据生成的 SQL 执行查询、插入、更新等操作。
3. 动态 SQL 的实现机制
MyBatis 使用了 OGNL(Object-Graph Navigation Language)表达式语言来处理动态 SQL 标签中的条件判断。这使得 MyBatis 可以在 XML 文件中通过 OGNL 表达式来控制 SQL 语句的生成。
例如,在 <if> 标签中:
<if test="name != null">AND name = #{name}</if>
MyBatis 会解析 test="name != null" 中的 OGNL 表达式,判断 name 是否为 null,如果不为 null,则将 AND name = #{name} 这部分 SQL 添加到最终的 SQL 中。
4. SqlSource 的解析
SqlSource 是 MyBatis 动态 SQL 的核心接口,MyBatis 提供了两种实现类:
StaticSqlSource:用于静态 SQL 查询,它只是将 SQL 作为字符串保存。DynamicSqlSource:用于动态 SQL 查询,负责根据参数动态生成 SQL。
DynamicSqlSource 是 MyBatis 处理动态 SQL 的关键类,它会解析动态 SQL 标签并根据实际的条件构建最终的 SQL。
动态 SQL 示例:DynamicSqlSource 处理过程
假设你有以下的动态 SQL 语句:
<select id="selectUser" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>
DynamicSqlSource创建:在解析过程中,MyBatis 会根据这个 SQL 语句创建一个DynamicSqlSource对象。SqlNode解析:DynamicSqlSource会将 XML 中的 SQL 语句分解成多个SqlNode,例如<where>和<if>标签会分别转换成WhereSqlNode和IfSqlNode。- SQL 拼接:当调用 SQL 时,
DynamicSqlSource会检查输入的参数,执行 OGNL 表达式,决定是否将每个动态部分(如AND name = #{name})添加到最终的 SQL 语句中。
5. 总结
- 动态 SQL 是 MyBatis 中根据条件动态生成 SQL 语句的功能,通常通过
<if>、<choose>、<foreach>等标签来实现。 - MyBatis 通过
SqlSource来构建 SQL,DynamicSqlSource会根据动态标签生成最终的 SQL 语句。 MappedStatement是 MyBatis 中封装 SQL 语句、参数类型、返回类型等元数据的对象,它包含了动态 SQL 语句的生成逻辑和执行信息。- 解析后的
MappedStatement会被Executor执行,最终根据不同的输入参数动态生成并执行 SQL。
动态 SQL 的解析过程是 MyBatis 强大功能的核心之一,通过灵活的 XML 标签和 OGNL 表达式,MyBatis 能够根据不同的业务需求生成灵活的 SQL 查询。
1640

被折叠的 条评论
为什么被折叠?



