Mybatis 动态 SQL

动态 SQL 元素:

  • if
  • choose(when, otherwise)
  • trim(where, set)
  • foreach

1 if

动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如:
1.1 1个条件

<select id="findActiveBlogWithTitleLike" resultType="Blog">
 select * from blog where state = "ACTIVE" 
 <if test="title != null">and title like #{title}</if>
</select>

注意 if 的条件是以 String 的形式作为 test 属性的值的。
1.2 多个条件

<if test="title != null and author.name != null">and title like #{title}</if>

注意传入的 Map 在条件中表达为 author.name,即 Map.key 的形式

2 choose ... when ... otherwise ...

choose ... when ... otherwise ... 映射成 Java 语法就是 switch ... case ... default...

应用场景:当不想应用所有的条件语句,而是根据条件选择其中一项。

<select id="findActiveBlogLike" resultType="Blog">
    select * from blog where state='ACTIVE'
    <choose>
        <when test="title !=null">
            and title like #{title}
        </when>
        <otherwise>
            and featured = 1
        </otherwise>
    </choose>
</select>

3 trim, where, set

只使用 if 语句带来的问题:

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 
  <if test="state != null">
    state = #{state}
  </if> 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

当所有条件都不成立时,此语句变成了select * from blog where

针对这种条件都不成立时拼接的 SQL 出错,有三种解决办法:
3.1 where

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state != null">
    state = #{state}
    </if> 
    <if test="title != null">
    AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
    AND author_name like #{author.name}
    </if>
  </where>
</select>

3.2 set 用来解决动态更新

<update id="updateAuthorIfNecessary">
    update author
    <set>
        <!--不要忘了逗号-->
        <if test="username != null">username=#{username},</if>
        <if test="password != null">password=#{password},</if>
        <if test="bio != null">bio=#{bio}</if>
    </set>
    where id=#{id}
</update>

3.3 trim
其实 where 和 set 都是 trim 的语法糖,where 和 set 的功能都可以用 trim 来表示

where 相当于

<trim prefix="where" prefixOverrides="AND/OR">

set 相当于

<trim prefix="set" suffixOverrides=",">

trim 标签有4个属性:

(其实无论是那个标签,它的作用都是把标签内部的 SQL 按照一定规则拼接起来,
然后再和标签外边的 SQL 拼接,最终形成完整的 SQL 语句)

  • prefix,前缀,trim 标签体中拼接字符串后的结果,prefix 会给这个结果加上一个前缀,如果 prefix = "where", 则加上 "where"
  • prefixOverrides, 前缀覆盖,去掉拼接结果的前缀
  • suffix, 后缀,它给拼接结果加上一个后缀,比如可以加上limit/order by
  • suffixOverrides, 后缀覆盖,去掉拼接结果的后缀,比如 set 中的“,”

Mybatis 传入参数为 list/array

传入参数为 list/array 时,在拼装成 sql 语句时还需要把它们取出来。这就需要使用 foreach。

foreach 在构建 in 条件中,它可以在 sql 语句中对集合进行迭代。

foreach 元素的属性

名称 作用
item 集合中每一个元素进行迭代时的别名
index 在迭代过程中,每次迭代到的位置
open 该语句以什么开始
separator 迭代元素之间的分隔符
close 该语句以什么结束
collection ???

例子

  1. 实体
public class Employees {  
    private Integer employeeId;  
    private String firstName;  
    private String lastName;  
    private String email;  
    private String phoneNumber;  
    private Date hireDate;  
    private String jobId;  
    private BigDecimal salary;  
    private BigDecimal commissionPct;  
    private Integer managerId;  
    private Short departmentId;  
}    
  1. dao 层
public interface EmployeesMapper {   
  
    List<Employees> getEmployeesListParams(List<String> employeeIds);  
  
    List<Employees> getEmployeesArrayParams(String[] employeeIds);  
  
    List<Employees> getEmployeesMapParams(Map<String,Object> params);  
}  
  1. sql
<select id="getEmployeesListParams" resultType="Employees">  
        select *  
        from EMPLOYEES e  
        where e.EMPLOYEE_ID in  
        <foreach collection="list" item="employeeId" index="index"  
            open="(" close=")" separator=",">  
            <!--注意这个变量名 employeeId 是代表的 item,需要和 item 保持一致-->
            #{employeeId}  
        </foreach>  
    </select>  
    
<select id="getEmployeesArrayParams" resultType="Employees">  
        select *  
        from EMPLOYEES e  
        where e.EMPLOYEE_ID in  
        <foreach collection="array" item="employeeId" index="index"  
            open="(" close=")" separator=",">  
            #{employeeId}  
        </foreach>  
    </select>  
    
<select id="getEmployeesMapParams" resultType="Employees">  
        select *  
        from EMPLOYEES e  
        <where>  
            <if test="departmentId!=null and departmentId!=''">  
                e.DEPARTMENT_ID=#{departmentId}  
            </if>  
            <if test="employeeIdsArray!=null and employeeIdsArray.length!=0">  
                AND e.EMPLOYEE_ID in  
                <foreach collection="employeeIdsArray" item="employeeId"  
                    index="index" open="(" close=")" separator=",">  
                    #{employeeId}  
                </foreach>  
            </if>  
        </where>  
    </select>  

Mybatis 动态 SQL

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 使用 jdbc 或类似的框架,动态拼接 SQL 是很痛苦的。比如根据当前日期选择数据表、根据传入的参数决定更新哪些...
    程序之心阅读 525评论 0 0
  • MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据...
    jackcooper阅读 498评论 0 1
  • 在mybtis中动态sql主要用到的几个节点元素有: 1、if2、choose(when, otherwise)3...
    Dl_毛良伟阅读 960评论 0 2
  • 、 、 、 :trim标签主要就是标记的作用,可以去掉if条件不满足时多余的and或者or或者,等等,和set标...
    小沙鹰168阅读 2,006评论 0 0
  • 我想象不出 作者:海桑 我想象不出 灵魂是什么形状 什么颜色 它可有体温,香味几何 如果我起身向它问好 它可报我以...
    已丑草阅读 276评论 0 0