# MyBatis教程 - 10 动态SQL

动态 SQL 是 MyBatis 中的一个强大特性,它允许在编写 SQL 语句时,根据不同的条件动态地改变 SQL 语句的结构。

例如在订单页面,可能会根据订单号、用户名、日期来查询订单,我们可以根据输入哪个条件来将这个条件动态的加入到 SQL 中,这就需要条件判断来动态的改变 SQL 语句。

MyBatis 提供了多个 XML 标签来支持动态 SQL,如 <if><choose><when><otherwise>)、<foreach><where><set> 等。下面详细介绍一下这些标签。

# 10.1 if条件判断

<if> 标签可以根据不同的条件来查询信息。

举个栗子:

UserMapper.xml 中定义 SQL 映射,如下:

<select id="findByConditions" resultType="User">
    SELECT * FROM tb_user
    WHERE 1=1
    <if test="username != null and username != ''">
        AND username = #{username}
    </if>
    <if test="email != null and email != ''">
        AND email = #{email}
    </if>
    <if test="age != null">
        AND age = #{age}
    </if>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13

上面使用了 <if> 标签,判断参数是否为空,当不为空的时候,才拼接 SQL。使用了 1=1 这个永远成立的条件,是为了当条件不满足,没有拼接 SQL 的时候,SQL 也是正确的命令。

针对上面的映射,只需要传递 usernameemailage 参数。

所以下面三种方式定义的接口都是可以的:

UserMapper.java :

/**
 * 根据条件查询用户
 */
List<User> findByConditions(User user);

/**
 * 根据条件查询用户
 */
List<User> findByConditions(Map<String, Object> map);

/**
 * 根据条件查询用户
 */
List<User> findByConditions(@Param("username") String username,  @Param("email") String email, @Param("age") Integer age);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

上面三种方式定义的接口,都可以映射到 xml 中的 SQL。

# 10.2 where标签

在上面使用 <if> 标签拼接条件,需要额外使用 1=1 来处理 WHERE,这样即使所有的查询条件为空,也会有 WHERE 条件判断。

其实我们可以使用 <where> 标签,它可以在生成 SQL 语句时智能地处理 WHERE 条件部分。

<where> 标签的作用:

  • 自动添加 WHERE 子句:当 SQL 中有条件时,<where> 标签会自动添加 WHERE 子句。
  • 自动去除多余的 ANDOR:在动态生成的 SQL 中,MyBatis 会自动去除开头的(后面的去不掉) ANDOR,避免 SQL 语法错误。

举个栗子,重新写一个多条件查询用户的例子:

内容未完......