动态SQL
动态SQL的简介:
MyBatis的强大特性之一便是它的动态 SQL。 如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。有些时候,SQL语句where条件中,需要一些
安全判断,**例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息。使用Oracle的序列、mySQL的函数生成Id。这时我们可以使用动态SQL。**利用动态 SQL 这一特性可以彻底摆脱这种痛苦。通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。 MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
Mybatis动态SQL主要元素:
- if和else
- choose(when,otherwise)
- trim
- set
- foreach
动态SQL元素详解
- if和else
查询语句块:
<select id="findUserList" parameterType="com.kang.pojo.UserQueryVo"
resultType="com.kang.pojo.UserCustom">
SELECT * FROM USER
<!--
where可以自动去掉条件中的第一个and
-->
<where>
<include refid="query_user_where"></include>
</where>
</select>
where元素的作用是会在写入where元素的地方输出一个where,另外一个好处是你不需要考虑where元素里面的条件输出是什么样子的,MyBatis会智能的帮你处理。如果所有的条件都不满足那么MyBatis就会查出所有的记录;如果输出后是and这个单词开头的,MyBatis会把第一个单词and忽略,当然如果是or开头的,MyBatis也会把它忽略。此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上。
SQL片段:
<sql id="query_user_where">
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</sql>
如果你提供了sex参数,那么就要满足sex!=null和sex!=’'两个条件,同样如果你提供了username参数的时候,也需要满足相应的条件,之后就是返回满足这些条件的所有user,这是非常有用的一个功能,以往我们使用其他类型框架或者直接使用JDBC的时候, 如果我们要达到同样的选择效果的时候,我们就需要拼SQL语句,这是极其麻烦的,比起来,上述的动态SQL就要简单多了。
如果输入是sex=1和username=null,那么上述配置产生的SQL语句就是:
SELECT * FROM USER where user.sex = #{userCustom.sex}
而不是:
SELECT * FROM USER and user.sex = #{userCustom.sex}
因为where标签自动加入了"where"这个关键字,而且去掉了"and"这个单词,并在where的前后自动加入了空格,最终组合成相应的SQL语句。
- choose
choose元素的作用就相当于JAVA中的switch语句,基本上跟JSTL中的choose的作用和用法是一样的,通常都是与when和otherwise搭配的。
使用示例:
<select id="findUserList" parameterType="com.kang.pojo.UserQueryVo"
resultType="com.kang.pojo.UserCustom">
SELECT * FROM USER
<choose>
<when test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex = #{userCustom.sex}
</when>
<when test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</when>
<otherwise>
and user.id = 1
</otherwise>
</choose>
</select>
when元素表示当when中的条件满足的时候就输出其中的内容,跟JAVA中的switch效果差不多的是按照条件的顺序,当when中有条件满足的时候,就会跳出choose,即所有的when和otherwise条件中,只有一个会输出,当所有的条件都不满足的时候就输出otherwise中的内容。
- trim
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能。
<select id="findUserList" parameterType="com.kang.pojo.UserQueryVo"
resultType="com.kang.pojo.UserCustom">
SELECT * FROM USER
<trim prefix="where" prefixOverrides="and |or">
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</trim>
</select>
- set
set元素主要是用在更新操作的时候,它的主要功能和where元素其实是差不多的,主要是在set标签包含的语句前输出一个set。如果包含的语句是以逗号结束的话将会把该逗号忽略。如果set包含的内容为空的话则会出错。有了set元素我们就可以动态的更新那些修改了的字段,而不用每次更新全部字段。
<update id="updateUser" parameterType="com.kang.pojo.User">
update user
<set>
<if test="username != null">
username=#{username},
</if>
<if test="birthday != null">
birthday=#{birthday},
</if>
<if test="sex != null">
sex=#{sex},
</if>
<if test="address != null">
address=#{address}
</if>
</set>
where id = #{id}
</update>
- foreach
动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
<select id="dynamicForeachTest" resultType="bean.TBlog">
select * from t_blog where id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。