动态SQL是MyBatis中一个强大的特性。
在JDBC代码中根据不同的条件拼写SQL语句是一件痛苦的事情,而且还容易出错。借助功能强大的基于 OGNL 的表达式,MyBatis的动态SQL在可以让你清晰高效地构建你的SQL语句,提升幸福感。
MyBatis3的常用标签主要有以下几种:
- if where
- choose (when, otherwise)
- trim set
- foreach
一起来看看怎么使用吧!
if where
这两个是我们最常用的标签语句,where语句根据条件来判断是否要包含if标签语句下的内容
select * from user
where age = 12
<if test="name != null">
and name = #{name}
</if>
这里如果用户传了非空的name值,就可以根据age和name两个条件来查询,不传的话默认就只根据age = 12这个条件来查询,如果还需要其他的条件语句,在下面继续添加即可
select * from user
where age = 12
<if test="name != null">
and name = #{name}
</if>
<if test="sex != null">
and sex = #{sex}
</if>
使用where标签对SQL进行智能预处理
如果where语句中没有age = 12这个默认条件
select * from user
where
<if test="name != null">
and name = #{name}
</if>
<if test="age != null">
and age = #{age}
</if>
这时用户不传name和age值,最终生成的SQL语句会像这样
select * from user
where
这显然不符合SQL语法规范,会报错的
如果传了name,SQL又会变成下面这样
select * from user
where and name = 'pname'
依然会报错
其实我们只要使用where标签语句就可以解决以上问题,SQL修改后如下
select * from user
<where>
<if test="name != null">
and name = #{name}
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
where标签语句会判断是否有if子语句满足条件,如果都不满足条件,整个where语句都会被移除,变成下面这样
select * from user
如果传入了name,where标签会判断语句的开头是否为“AND”或者“OR”,如果是会自动去除
select * from user
where name = 'pname'
常见问题
如果传入的对象参数中没有指定的字段,而你又在if语句中使用了该字段
select * from user
<where>
<if test="nickname != null">
and name = #{nickname}
</if>
</where>
传入的User实体中根本没有nickname属性,这时会报以下错误
choose when otherwise
choose语句可以实现类似我们Java中switch语句的功能,按顺序对when子句进行条件匹配,满足条件就会使用该when标签下的语句
select * from user
<where>
<choose>
<when test="name != null">
and name = #{name}
</when>
<when test="age != null">
and age = #{age}
</when>
<otherwise>
and sex = 'male'
</otherwise>
</choose>
</where>
这时会有以下几种情况:
- 如果只传了name,那么会使用name-when下的条件语句
- 如果只传了age,那么会使用age-when下的条件语句
- 如果name和age都没有传,这时会使用otherwise标签下的语句
- 如果name和age都传了,这时按照顺序,name-when子句满足条件,将直接使用该标签下的语句,不会再继续向下判断age-when子句了
注意:choose标签语句也要放在where标签下,否则也会出现跟上面if语句一样的问题
trim set
set标签主要用来实现动态更新功能的
update user
<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</set>
where id = #{id}
trim标签的作用
- 在SQL语句前拼接“where”、“set”和“values(”等前缀
- 在SQL语句后拼接“)”等后缀
- 去除SQL中多余的“and”、“or”以及“,”
如何使用trim
trim标签下有四个属性
- prefix - 在SQL前要拼接的内容
- prefixOverrides - SQL中要去除的多余的开头内容,如“and”、“or”之类的
- suffix - 在SQL后要拼接的内容
- suffixOverrides - SQL中要去除的多余的结尾内容,如多余的“,”
实现类似where标签的功能
select * from user
<trim prefix="where" prefixOverrides="AND |OR ">
<if test="name != null">
and name = #{name}
</if>
<if test="age != null">
and age = #{age}
</if>
</trim>
实现类似set标签的功能
<update id="updateByPrimaryKeySelective">
update user
<trim prefix="set" suffixOverrides=",">
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</trim>
where id = #{id}
</update>
foreach
foreach标签的作用就对集合进行遍历,经常被用来构建IN条件语句
比如我们传入一个字符串集合nameList,然后查询name在这个集合中的User数据
select * from user
<where>
<if test="nameList != null">
and name in
<foreach collection="nameList" open="(" separator="," close=")" item="name">
#{name}
</foreach>
</if>
</where>
- collection - 指定集合属性的名称,这里是nameList
- open - 指定拼接SQL的开头前缀,这里是“(”
- separator - 分隔符,这里是“,”
- close - 指定拼接SQL的结束尾缀,这里是“)”
- item - 代表当前遍历集合中一个元素,这里是一个name
这样拼接后的语句如下
select * from user WHERE name in ( ? , ? )
foreach标签还有两个属性,index(表示当前迭代的序号)和nullable(表示集合是否可以为空)
其他
bind标签常用来创建一个变量,可以在上下文中使用
select * from user
<where>
<if test="name != null">
<bind name="nameLike" value="'%' + name + '%'"/>
and name like #{nameLike}
</if>
</where>
注意:bind的value属性中,没有使用#{name}来获取name属性的值,而是直接用name来获取属性值。
本文介绍了MyBatis常用标签的使用方法和注意事项,希望可以帮到你,有问题可以在评论区交流下,欢迎点赞评论关注。