MyBatis 动态SQL
在 MyBatis 中的动态 SQL,就是根据不同的条件生成不同的 SQL 语句。
一、if
1. 语法
1 |
|
当条件成立时,if 标签内包裹的 SQL 语句生效。
2. 示例
1 |
|
当仅传入 author 时,SQL 语句为:
1 |
|
当传入 author 和 title 时,SQL 语句为:
1 |
|
当仅传入 title 时,SQL 语句为:
1 |
|
二、choose、when 和 otherwise
1. 说明
choose、when 和 otherwise 配合使用,它们类似于 switch 语句。
2. 语法
1 |
|
when 之间和 when 与 otherwise 是互斥的
- 当条件 1 成立时,仅有 SQL 语句 1 生效
- 当条件 2 成立时,仅有 SQL 语句 2 生效
- 当条件 1 和条件 2 均不成立时,仅有 SQL 语句 3 生效
3. 示例
1 |
|
当传入 author 时,SQL 语句为:
1 |
|
当不传入 author 且传入 title 时,SQL 语句为:
1 |
|
当 author 和 title 均没有传入时,SQL 语句为:
1 |
|
三、where、set 和 trim
1. 问题
MyBatis 的动态 SQL 最终要拼接成 SQL 语句,所以应该遵循 SQL 的规范。
注意到在 SQL 语句中:
(1) where
1 |
|
SQL 中的 where 子句,有以下要求:
有条件时,应该有 where,
无条件时,不应该有 where
第一个条件前不加 and/or
其它条件之前应该加 and/or,以连接条件
(2) set
1 |
|
SQL 中的 set 语句,有以下要求:
- 不同的赋值语句之间用
,
进行分隔 - 最后一个赋值语句之后不应加
,
(3) 复杂的动态拼接
因此,MyBatis 中的动态拼接也不得不写得臃肿繁杂,例如:
1 |
|
MyBatis 引入了 where、set 和 trim 用于解决这一问题。
2. where
1 |
|
where 的作用是:
- 当有条件成立时,添加 where
- 删除第一个 SQL 语句中开头的 and/or
因此,上述案例可以重写为:
1
2
3
4
5
6
7
8
9
10
11
12
select
*
from
blog
<where>
<if test="author != null">
and author like #{author}
</if>
<if test="title != null">
and title like #{title}
</if>
</where>
3. set
1 |
|
set 的作用是:
- 当有条件成立时,添加 set
- 删除最后一个赋值语句之后的
,
4. trim
(1) 说明
where 和 set 本质上是 trim 。
trim 标签的作用的:
- 可以通过配置 prefix 或 suffix,当标签包裹语句时,增加前缀或增加后缀
- 可以通过配置 prefixOverrides 或 suffixOverrides,删除语句开头或结尾的关键字
(2) 属性
属性 | 描述 |
---|---|
prefix | 增加前缀 |
suffix | 增加后缀 |
prefixOverrides | 删除语句开头的关键字 |
suffixOverrides | 删除语句末尾的关键字 |
(3) 实现 where
1 |
|
- 当标签包裹语句时,增加 WHERE 前缀
- 删除语句前的 and 或 or
(4) 实现 set
1 |
|
- 当标签包裹语句时,增加 SET 前缀
- 删除语句后的
,
四、foreach
1. 语法
1 |
|
- 在 SQL 片段中,
- 使用
#{item}
或${item}
获取每个元素 - 使用
#{index}
或${index}
获取每个元素的下标
- 使用
- collection 指定遍历的集合
- open 指定整个 foreach 开头要拼接的字符串
- separator 指定每个 SQL 片段之间的分隔符
- close 指定整个 foreach 结尾要拼接的字符串
2. 示例
1 |
|
五、bind
bind 元素用于创建变量。
1
2
3
4
5
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
六、script
在使用注解定义 SQL 映射时,可以通过 script 标签来使用动态 SQL。
1
2
3
4
5
6
7
8
9
10
11
@Update({"<script>",
"update Author",
" <set>",
" <if test='username != null'>username=#{username},</if>",
" <if test='password != null'>password=#{password},</if>",
" <if test='email != null'>email=#{email},</if>",
" <if test='bio != null'>bio=#{bio}</if>",
" </set>",
"where id=#{id}",
"</script>"})
void updateAuthorValues(Author author);