介绍
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
简而言之,动态SQL简化了SQL语句拼接环境
1
2
3
4
5
6
7
8 create table blog
(
id varchar(50) not null comment '博客id',
title varchar(100) not null comment '博客标题',
author varchar(30) not null comment '博客作者',
create_time datetime not null comment '创建时间',
views int(30) not null comment '浏览量'
);
已经提前加入几条数据。
if
接口
1 | public interface BlogMapper { |
BlogMapper.xml
1 | <select id="queryBlogIF" parameterType="map" resultType="Blog"> |
官方文档上写where state='ACTIVATE'
,但是在我的环境中会报错,用where 1=1
替代是一样的效果,表示恒成立,即使if后面的语句不执行,也能查询出东西。
完整标签为<if test="判断条件"></if>
choose(when,otherwise)
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
接口
1 | public interface BlogMapper { |
BlogMapper.xml
1 | <select id="queryBlogChoose" parameterType="map" resultType="Blog"> |
注意:此处使用\where 1=1
语句,相比后者,前者更优雅地实现了智能拼接。在此例中,如果”title!=null”不成立且”author!=null”成立,在最后拼接时\where and author=#{author}
这样的错误语句并去掉and。
set
接口
1 | public interface BlogMapper { |
BlogMapper.xml
1 | <update id="updateBlog" parameterType="map"> |
在使用update语句时容易出现的拼接问题是逗号后面紧跟一个where,例如此例中可能会出现update blog set author=#{author}, where id=#{id}
的情况,因此\
SQL片段
我们可以用\1
2
3
4
5
6
7
8<sql id="if-title-author">
<if test="title!=null">
title = #{title}
</if>
<if test="author!=null">
and author =#{author}
</if>
</sql>
需要使用的时候:1
<include refid="if-title-author"/>
即可实现代码的复用。
注意事项:
- 最好基于单表来定义SQL片段
- 不要存在where标签
foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。
假设现在需要查询id为1,2,3的三条数据,SQL语句为select * from blog where 1=1 and (id=1 or id=2 or id=3)
使用foreach标签
接口
1 | public interface BlogMapper { |
BlogMapper.xml
1 | <select id="queryBlogForeach" parameterType="map" resultType="blog"> |
foreach标签中collection是集合,item是集合中的对象(很类似于java中的for(:)
语句),open是开头,seperator是分隔符,close是结尾。以这样的方式来拼接SQL语句。
此例中最终拼接成的语句为:select * from blog where 1=1 and (id=1 or id=2 or id=3)
Test.java
1 | @Test |