动态 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 | ??? |
例子
- 实体
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;
}
- dao 层
public interface EmployeesMapper {
List<Employees> getEmployeesListParams(List<String> employeeIds);
List<Employees> getEmployeesArrayParams(String[] employeeIds);
List<Employees> getEmployeesMapParams(Map<String,Object> params);
}
- 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>