前言
在实际开发中,免不了要使用到SQL语句判断,当符合某个条件时执行某条语句,这就是动态SQL。在原生JDBC中,采用动态拼接的方式实现,而mybatis则使用动态SQL标签来实现,
if标签
在mybatis中使用 if 标签来表示判断条件,如以下语句:
<select id="selectById" resultType="view">
select * from view
where 1=1
<if test="author">
and author = #{author}
</if>
<if test="id > 0">
and id = #{id}
</if>
</select>
在上述代码中可以看到需要判断的语句都是用 if 标签包裹起来,test中表示判断条件,如第一个的 <if test=“author”> 表示如果传进来的参数author不为null则拼接以下语句;
在真实开发中,并不是所有条件都是以null为判断的,所以也可以在test属性中直接写判断条件,就好比第二个 if 标签一样。
需要注意的是,两个 if 标签是并列关系,即不管第一个 if 语句是否成立,不影响后续 if 标签的判断执行; 如果没有一个 if 标签符合,那么 where 后面就是 1, SQL就会进行全表查询,原因是 1=1 的缘故,所以 if 标签语句都需要加上 and ,这样才不会因为某个 if 标签的不成立而使得SQL语句出现语法错误;当然,后续会使用 where 标签来解决该问题。
choose标签
choose标签是一个系列标签,顾名思义就是选择标签,即多个choose标签中,从上到下执行,只要有一个满足条件,则其余的不会再执行,和Java中的switch类似。常见的choose标签是when和otherwise。
when标签是指当条件成立时进行的操作,从上到下执行,一旦有一个when标签的条件满足,则不会进行后续操作,如以下代码得出的结果可以看到:
<select id="select" resultType="view" parameterType="view">
select * from view
where 1=1
<choose>
<when test="view.title != null">
and title like concat('%', #{view.title}, '%')
</when>
<when test="author != null">
and author concat('%', #{view.author}, '%')
</when>
</choose>
</select>
@Test
public void select(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
viewMapper mapper = sqlSession.getMapper(viewMapper.class);
View view = new View();
view.setTitle("MySQL");
view.setAuthor("666");
List<View> select = mapper.select(view);
for (View views : select){
System.out.println(views.toString());
}
结果:
在上述代码中我传递了title和author的参数,但是代码只拼接了title的SQL语句,这就是选择标签。
选择标签中还有otherwise,它的作用更加简单,当选择标签中都不满足的时候执行该语句。
需要注意的是,两个标签都需要在<choose>的包裹下,且是有顺序的,要求otherwise在when标签的下方。
trim标签
where标签
<select id="selectById" resultType="view">
select * from view
where
<if test="author">
author = #{author}
</if>
<if test="id > 0">
and id = #{id}
</if>
</select>
这是if标签代码,这个语句是会报错的,因为无法确定author的条件是否回城里,如果不成立那么SQL语句就会出现语法错误,尽管可以使用原生JDBC拼接的方法使用 where 1=1,但是Mybatis推出where标签能够完美解决这个问题,在where标签下,如果第一个if标签成立,而SQL语句中存在 and会将其去除;反之如果后续的if标签成立但没有加 and,mybatis会将其加上。
代码:
<select id="selectWhere" resultType="view">
select * from view
<where>
<if test="view.id > 0">
and id = #{view.id}
</if>
<if test="view.author != null">
and author like concat('%', #{author}, '%');
</if>
</where>
</select>
set标签
set标签的用法和where一致,and的拼接都是采用where的标准,只是其的作用不一致罢了,set标签是用来修改数据的。
代码:
<update id="updateById">
update view
<set>
<if test="author != null">
statue = 10201,
</if>
</set>
where author=#{author}
</update>
trim标签
trim是where和set的原型,where和set标签其实都是trim封装好的形式,现在使用trim去标签where和set。
<select id="selectWhere" resultType="view" >
select * from view
<trim prefix="where" prefixOverrides="and |or">
<if test="view.id > 0">
and id = #{view.id}
</if>
<if test="view.author != null">
or author like concat('%', #{view.author}, '%')
</if>
</trim>
</select>
trim标签有四个属性:prefix,prefixOverrides,suffix,suffixOverrides;它们所代表的含义是:
prefix:添加对应的前缀
suffiix:添加对应的后缀
prefixOverrides:去除多余的前缀
suffixOverrides :去除多余的后缀
foreach
foreach是一个功能强大的标签,可以遍历参数。collection属性表示传递进来的参数集合的名称,item表示当前的值,index则表示索引,open表示使用什么东西进行开头,separator表示遍历中值和值之间用什么进行分隔,close表示用什么结尾。
foreach不仅可以遍历顺序表,还可以遍历Map,遍历Map时index就变成了键,item就变成了值。
<select id="selectByInId" resultType="view">
select * from view
<where>
<if test="ids != null">
id in
<foreach collection="ids" item="id" index="index"
open="(" separator="," close=")">
#{id}
</foreach>
</if>
and statue = 10201;
</where>
</select>