MyBatis 提供了动态 SQL 功能,允许在 SQL 查询中根据条件动态构建不同的 SQL 语句。使用动态 SQL 可以根据不同的条件拼接 SQL 语句,从而提升代码的灵活性和可维护性。MyBatis 中的动态 SQL 主要通过 XML 映射文件中的动态标签来实现。

常用的动态 SQL 标签

<if>
用于根据条件判断是否生成 SQL 片段。

<select id="selectUser" resultType="User">
    SELECT * FROM users
    <where>
        <if test="name != null">AND name = #{name}</if>
        <if test="age != null">AND age = #{age}</if>
    </where>
</select>

该查询会根据 nameage 是否为空来动态拼接 SQL 语句。

<choose><when><otherwise>
类似于 Java 中的 if-else 语句,用于根据多个条件选择执行不同的 SQL 语句。

<select id="selectUser" resultType="User">
    SELECT * FROM users
    <where>
        <choose>
            <when test="status == 'active'">AND active = 1</when>
            <when test="status == 'inactive'">AND active = 0</when>
            <otherwise>AND active IS NULL</otherwise>
        </choose>
    </where>
</select>

这段 SQL 会根据 status 值选择不同的 SQL 片段。

<foreach>
用于循环处理集合类型的参数,例如数组、List 等,生成批量 SQL 语句。

<select id="selectUsersByIds" resultType="User">
    SELECT * FROM users
    <where>
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </where>
</select>

如果 ids 是一个列表,<foreach> 会将每个 id 包装在 () 中,并用逗号分隔。

<set>
用于动态生成 UPDATE 语句的 SET 部分。在 SQL 中,SET 后的字段更新会根据条件拼接。

<update id="updateUser">
    UPDATE users
    <set>
        <if test="name != null">name = #{name},</if>
        <if test="age != null">age = #{age},</if>
    </set>
    WHERE id = #{id}
</update>

通过 <set> 标签,可以动态地添加要更新的字段。如果某个字段为空,<if> 会避免添加该字段。

<trim>
用于在动态 SQL 语句中移除不必要的前缀和后缀,例如 ANDOR

<select id="selectUser" resultType="User">
    SELECT * FROM users
    <where>
        <trim prefix="AND" prefixOverrides="AND ">
            <if test="name != null">name = #{name}</if>
            <if test="age != null">age = #{age}</if>
        </trim>
    </where>
</select>

prefix="AND" 会在所有条件前加上 AND,而 prefixOverrides="AND " 会去除首部的 AND

<bind>
用于在 SQL 中创建临时变量。它可以将参数值或表达式赋给一个临时变量,然后在 SQL 中引用该变量。

<select id="selectUser" resultType="User">
    <bind name="prefix" value="'%' + name + '%'" />
    SELECT * FROM users WHERE name LIKE #{prefix}
</select>

通过 <bind>,可以创建一个 prefix 临时变量,并在 SQL 中使用。

示例:动态 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>
        <if test="status != null">AND status = #{status}</if>
    </where>
</select>

在这个例子中,<where> 标签自动为每个条件添加 AND,如果没有条件,<where> 会去掉不必要的 AND

小结

MyBatis 提供的动态 SQL 使得 SQL 查询更加灵活,可以根据实际需求动态构建 SQL 语句。常用的动态 SQL 标签包括 <if><choose><foreach><set><trim> 等,它们可以帮助开发者根据不同的业务需求生成不同的 SQL 查询。