MyBatis的一个强大的特性之一通常是它的动态SQL能力。提供了OGNL表达式动态生成SQL的功能。动态SQL有:

  1. if
  2. choose,when,otherwise
  3. where,set
  4. foreach

if

场景:查询男性用户,如果输入了姓名,则按姓名查询

  1. List<User> queryUserList(@Param("name") String name);
  1. <select id="queryUserList" resultType="com.example.test.model.User">
  2. select * from tb_user WHERE sex=1
  3. <if test="name!=null and name.trim()!=''">
  4. and name like '%${name}%'
  5. </if>
  6. </select>

choose..when..otherwise

场景:查询男性用户,当输入了姓名则按照姓名模糊查找,当输入了年龄则按照年龄查找,否则查找姓名为“xiaoyu”的用户。

List<User> queryUserListByNameOrAge(@Param("name") String name,@Param("age") Integer age);
<select id="queryUserListByNameOrAge" resultType="com.example.test.model.User">
    select * from tb_user WHERE sex=1
    <!--
        1. 一旦有条件成立的when,后续的when则不会执行
        2. 当所有的when都不执行时,才会执行otherwise
    -->
    <choose>
        <when test="name!=null and name.trim()!=''">
            and name like '%${name}%'
        </when>
        <when test="age!=null">
            and age = #{age}
        </when>
        <otherwise>
            and name='xiaoyu'
        </otherwise>
    </choose>
</select>

where

场景:查询所有用户,如果输入了姓名按照姓名进行模糊查询,如果输入年龄,按照年龄进行查询,如果两者都输入,两个条件都要成立。

List<User> queryUserListByNameAndAge(@Param("name") String name,@Param("age") Integer age);
<select id="queryUserListByNameAndAge" resultType="com.example.test.model.User">
    select * from tb_user
    <!--如果多出一个and,会自动去除,如果缺少and或者多出多个and则会报错-->
    <where>
        <if test="name!=null and name.trim()!=''">
            and name like '%${name}%'
        </if>
        <if test="age!=null">
            and age = #{age}
        </if>
    </where>
</select>

set

场景:修改用户信息,输入什么字段就改什么字段

public void updateUser(User user);
<update id="updateUser" parameterType="com.example.test.model.User">
    UPDATE tb_user
    <set>
        <if test="userName!=null">user_name = #{userName},</if>
        <if test="password!=null">password = #{password},</if>
        <if test="name!=null">name = #{name},</if>
        <if test="age!=null">age = #{age},</if>
        <if test="sex!=null">sex = #{sex},</if>
        <if test="birthday!=null">birthday = #{birthday},</if>
        updated = now(),
    </set>
    WHERE
    (id = #{id});
</update>

foreach

场景:按照多个id查询用户信息。

List<User> queryUserListByIds(@Param("ids") Long[] ids);
<select id="queryUserListByIds" resultType="com.example.test.model.User">
    select * from tb_user where id in
    <foreach collection="ids" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</select>

trim

如果 where 元素没有按正常套路出牌,我们还是可以通过自定义 trim 元素来定制我们想要的功能。比如,和 where 元素等价的自定义 trim 元素为:

<trim prefix="WHERE" prefixOverrides="AND | OR">
  ...
</trim>

trim 也可用于比如set的操作:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

举例:

<update id="updateUser" parameterType="com.example.test.model.User">
    UPDATE tb_user
    <trim prefix="set" suffixOverrides=",">
        <if test="userName!=null">user_name = #{userName},</if>
        <if test="password!=null">password = #{password},</if>
        <if test="name!=null">name = #{name},</if>
        <if test="age!=null">age = #{age},</if>
        <if test="sex!=null">sex = #{sex},</if>
        <if test="birthday!=null">birthday = #{birthday},</if>
        updated = now(),
    </trim>
    WHERE
    (id = #{id});
</update>

bind

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>