动态sql
什么是动态sql:动态SQL就是根据不同的条件产生的不同SQL语句。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
1. 搭建环境
CREATE TABLE blog(
id VARCHAR(50) not NULL comment '博客id',
title varchar(200) NOT null COMMENT '博客标题',
author varchar(20) not null comment '博客作者',
create_time datetime not null comment '创建时间',
views int(30) not null comment '浏览量'
)engine innoDB default charset=utf8;
2.if
<select id="queryBolgIf" parameterType="map" resultType="blog">
select * from blog where 1=1
<if test="title!=null">
--模糊查询,要使用like,并且要搭配"%"
and title like "%"#{title}"%"
</if>
<if test="author!=null">
and author like "%"#{author}"%"
</if>
</select>
3.Choose(when, otherwise)
chooes–when–otherwise语句,只会选择其中的一个执行,如果存在otherwise语句,且when中的语句都不通过,那么就执行otherwise,如果不存在otherwise语句,且when语句都不成立,就不进行拼接sql,也就是不执行chooes里面的语句。
<select id="queryBolgChoose" parameterType="map" resultType="blog">
select * from blog
<where>
<choose>
<when test="title!=null">
title like "%"#{title}"%"
</when>
<when test="author!=null">
and author like "%"#{author}"%"
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
4.trim(where, set)
where标签,可以用于在sql中自动拼接where关键字,并且可以去除标签内多余的and/or,保证sql的正确性
<select id="queryBolgIf" parameterType="map" resultType="blog">
select * from blog
<!--这里的where标签,可以可以在sql语句中智能的添加where关键字,
如果where标签里面的条件都不成立,则where关键字不会在sql语句中添加where关键字
如果where标签内有一个条件成立,它会智能的判断这条新加的sql语句有没有and/or连接词,如果有,会去掉
如果where标签内有多个条件成立,反正sql语句中直接跟在where关键字后面的语句是会智能的去掉and/or关键字,如果有and/or关键字的话-->
<where>
<if test="title!=null">
title like "%"#{title}"%"
</if>
<if test="author!=null">
<!--如果这个条件成立,上面的条件不成立,但是这个语句有and,and就会被去掉-->
and author like "%"#{author}"%"
</if>
</where>
</select>
set标签,可以用于在sql中自动拼接set关键字,并且可以去除标签内多余的逗号(,),保证sql的正确性
<insert id="updateBlog" parameterType="map">
update blog
<set>
<if test="title!=null">
title = #{title},
</if>
<if test="author!=null">
author = #{author},
</if>
</set>
where id = #{id}
</insert>
trim就是可以替换前缀和后缀,效果和where/set 的相同。
5.foreach
使用foreach使sql更加灵活。
<!--foreach就是遍历的意思,遍历集合,所以我们需要传递一个集合给它collection的值就是传递的集合,
item就是集合的每一项,下面的语句会进行取值#{},open和close定义了遍历开始的头和尾需要添加的一些操作(一般是括号), separator,定义了每个元素使用什么隔开(一般是and、or或者逗号(,),根据需求定义即可)-->
<select id="queryBolgForEach" parameterType="map" resultType="blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="(" close=")" separator="or">
<!--等式左边的id是blog表中的字段,右边的id是从传递过来的集合中去出的值item="id"-->
id = #{id}
</foreach>
</where>
</select>
<!--<select id="queryBolgForEach" parameterType="map" resultType="blog">-->
<!-- select * from blog where (id=#{id1} or id=#{id2} or id=#{id3})-->
<!--</select>-->
6.SQL片段
可以用于提取可以公用的sql片段,提高代码复用率。
-
使用SQL标签提取公共部分
<sql id="if-title-author"> <if test="title!=null"> title like "%"#{title}"%" </if> <if test="author!=null"> and author like "%"#{author}"%" </if> </sql>
-
在需要使用的地方使用标签include引用即可
<select id="queryBolgIf" parameterType="map" resultType="blog"> select * from blog <where> <include refid="if-title-author"/> </where> </select>
注意事项:
- 提取的公共SQL语句不要太复杂,这样会降低代码的复用率,共用的sql语句尽量简单。
- 提取的SQL语句中,最好不要包含where/set标签,这样也会降低代码复用率,而且可能会出问题。
所谓的动态SQL,本质上还是SQL,只不过在SQL层面的代码中执行一些逻辑代码,对SQL语句进行一些动态的控制