MyBatis 的动态 SQL 机制是通过在 SQL 语句中灵活地插入条件、拼接部分 SQL 或选择不同的 SQL 语句来实现的。MyBatis 提供了 <if>
, <choose>
, <when>
, <otherwise>
, <where>
, <trim>
, <foreach>
等标签,来支持动态生成 SQL 查询。其核心原理是通过在执行时根据参数条件来动态拼接 SQL 语句。以下是 MyBatis 动态 SQL 执行的基本原理和工作流程:
1. 动态 SQL 标签
MyBatis 提供了丰富的动态 SQL 标签,帮助开发者根据不同的查询条件动态生成 SQL 语句:
<if>
标签: 根据条件判断是否生成某个 SQL 片段。<choose>
: 类似于 Java 中的if-else
语句,用于选择满足条件的 SQL 片段。<when>
: 配合<choose>
标签使用,表示符合某个条件的 SQL 片段。<otherwise>
: 与<choose>
配合,表示当所有<when>
条件不成立时执行的 SQL 片段。<trim>
: 用于移除多余的 SQL 关键字(如前导空格、前导逗号等)。<foreach>
: 用于处理集合类型的参数,动态地生成 SQL 片段。
2. 动态 SQL 的执行原理
MyBatis 动态 SQL 的执行过程可以分为以下几个步骤:
2.1 解析 SQL 映射文件
MyBatis 在启动时会读取映射文件中的 SQL 配置。SQL 中可能包含动态 SQL 标签(如 <if>
, <choose>
, <foreach>
等),MyBatis 会在执行前解析这些动态标签。
2.2 根据参数判断条件
当调用某个映射方法时,MyBatis 会根据传入的参数判断哪些动态 SQL 标签应该生效。例如,<if>
标签中的条件表达式会通过 OGNL(Object-Graph Navigation Language)对传入的参数进行判断。
- 如果
<if>
标签的条件为true
,则将包含在该标签内的 SQL 语句片段加入到最终的 SQL 中。 - 如果条件为
false
,则该 SQL 片段被忽略。
2.3 生成最终 SQL 语句
根据传入参数和动态标签的条件,MyBatis 会动态地拼接 SQL 语句。这个拼接过程发生在 MyBatis 的解析阶段,目的是根据当前方法传入的参数动态生成完整的 SQL。
例如,假设我们有如下的动态 SQL:
XML
<select id="findUser" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>
-
当
name
和age
都不为null
时,生成的 SQL 会是:sqlSELECT * FROM users WHERE name = ? AND age = ?
-
当只有
name
为null
时,生成的 SQL 会是:sqlSELECT * FROM users WHERE age = ?
2.4 绑定参数
在 SQL 语句生成后,MyBatis 会将参数值绑定到 SQL 中的占位符(?
)。这些占位符会根据动态 SQL 中的 #{}
语法被替换为实际的参数值。
2.5 执行 SQL
最后,生成的 SQL 语句会通过 JDBC 执行,MyBatis 会将结果映射回 Java 对象或集合中。
3. 执行过程总结
- XML 配置解析 :MyBatis 读取映射文件中的动态 SQL 标签(如
<if>
,<choose>
,<foreach>
等)并解析它们。 - 条件判断:在执行时,MyBatis 根据传入的参数判断哪些 SQL 标签的条件满足,并决定是否将相关的 SQL 片段包含在最终的 SQL 中。
- 生成 SQL:根据条件判断结果,MyBatis 动态生成 SQL 查询语句。
- 参数绑定:MyBatis 将查询方法的参数绑定到 SQL 中的占位符。
- 执行 SQL:最终生成的 SQL 被执行,结果返回给调用者。
通过动态 SQL 标签,MyBatis 可以灵活地生成 SQL,减少冗余的代码,并提升 SQL 查询的复用性。