MyBatis动态SQL第一篇之实现多条件查询(if、where、trim标签)

一、动态SQL概述

以前在使用JDBC操作数据时,如果查询条件特别多,将条件串联成SQL字符串是一件痛苦的事情。通常的解决方法是写很多的if-else条件语句对字符串进行拼接,并确保不能忘了空格或在字段的最后省略逗号。MyBatis使用动态SQL来改善这种情形,动态SQL是基于OGNL的表达式,可方便我们在SQL语句中实现某些逻辑。用于实现动态SQL的元素如下。

  • if:利用if实现简单的条件选择
  • choose(when,otherwise):相当于Java中的switch语句,通常与when和otherwise搭配使用
  • set:解决动态更新语句
  • trim:可以灵活的去除多余的关键字
  • foreach:迭代一个集合,通常用于in条件

二、if用法

在查询条件不是很多并且较为固定的情况下,最好的解决方案是采用多参数直接入参的方式,这样代码比较清晰,可读性强。如下

public interface UserMappper{
    public List<User> getUserList(@Param("userName") String userName,
                                  @Param("userRole") Integer roleId);
}
<select id="getUserList" resultMap="userList">
  select u.*, r.roleName from smbms_user u, smbms_role r
  where u.userName like connect ('%', #{userName}, '%')
  and u.userRole=#{userRole} and u.userRole=r.id
</select>

在上述代码中,参数使用了@Param注解,并将参数roleId重命名为userRole

测试上述代码,如下

  • 在两个条件都给出的情况下,如String userName="孙"; Integer roleId=3,此时会输出正确结果;
  • 若传入的用户角色roleId为空,即只按用户名称进行模糊查询,如String userName="孙"; Integer roleId=null,此时输出的结果不满足需求:没有输入用户角色的情况下,只根据用户名称进行模糊查询的需求;
  • 若传入的用户用户名称userName为“”(空字符串),roleId有值(roleId=3),此时结果是正确的;

针对上述这种某字段用户输入可能为空的情况,我们使用动态SQL的if元素来实现多条件查询,如下

<select id="getUserList" resultMap="userList">
  select u.*, r.roleName from smbms_user u, smbms_role r where u.userRole=r.id
    <if test="userRole != null">
      and u.userRole = #{userRole}
    </if>
    <if test="userName != null and userName != ''">
      and u.userName like concat('%', #{userName}, '%')
    </if>
</select>

在上述代码中,利用if元素实现简单的条件判断,if元素的test属性表示进入if内需要满足的条件。此时对于String userName="孙"; Integer roleId=null这种情况,输出了正确结果。

三、if+where用法

单表查询,考虑如下代码

<select id="getUserList" resultType="User">
  select * from smbms_user where
    <if test="userName != null and userName != ''">
      u.userName like concat('%', #{userName}, '%')
    </if>
    <if test="userRole != null">
      and u.userRole = #{userRole}
    </if>
</select>

此时对于String userName=""; Integer roleId=3这种情况,会报错,因为多了一个“and”。

针对这种and、where的处理,可使用动态SQL的where元素,where元素主要用来简化SQL语句中的where条件判断,并智能的处理and和or,不必担心多余关键字导致的语法错误。如下

<select id="getUserList" resultType="User">
  select * from smbms_user
    <where>
      <if test="userName != null and userName != ''">
        and u.userName like concat('%', #{userName}, '%')
      </if>
      <if test="userRole != null">
        and u.userRole = #{userRole}
      </if>
    </where>
</select> 

where元素标签会自动标识其标签内是否有返回值,若有,就插入一个where。此外,若该标签返回的内容是以and或者or开头的,会自动剔除。此时对于String userName=""; Integer roleId=3这种情况会正确输出

四、if+trim用法

除了where元素之外,还可以使用trim元素来替代where元素,并实现与where元素相同的效果。

trim元素也会自动识别其标签内是否有返回值,若有返回值,则在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;trim也可把包含内容首部的某些内容覆盖(即忽略),或者把尾部的某些内容覆盖,与之对应的属性是prefixOverrieds和suffixOverrieds。

<select id="getUserList" resultType="User">
  select * from smbms_user
  <trim prefix="where" prefixOverrides="and | or">
    <if test="userName != null and userName != ''">
      and u.userName like concat('%', #{userName}, '%')
    </if>
    <if test="userRole != null">
      and u.userRole = #{userRole}
    </if>
  </trim>
</select>

prefixOverrides:对于trim包含内容的首部进行指定内容的忽略

posted @ 2019-10-20 17:31  请叫我小老弟  阅读(20309)  评论(1编辑  收藏  举报