什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句
利用动态SQL这一特性可以彻底摆脱JDBC之前拼接sql的痛苦
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少
if
choose (when, otherwise)
trim (where, set)
foreach
例子一:
<!--添加语句-->
<insert id="addBlog" parameterType="blog">
insert into mybatis.blog (id,title,author,create_time,views)
values(#{id},#{title},#{author},#{createTime},#{views})
</insert>
<!--需求:传title的时候按照title查 传author的时候按照author查 什么都不传查所有的-->
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<!--test必填 test里面写表达式:判断一些东西-->
<where>
<if test="title != null"><!--如果title不为空把这句话加上去-->
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
<select id="queryBlogChoose" resultType="blog" parameterType="map">
select * from mybatis.blog
<where>
<choose>
<when test="title!=null">
title = #{title}<!--第一个语句不用加and 后面的要加 如果第一个不成立 由于有where的存在 会自动把and去掉-->
</when>
<when test="author!=null">
and author = #{author}
</when>
<otherwise>
and views = #{views}<!--如果两个条件都不成立执行这个-->
</otherwise>
</choose>
</where>
</select>
<update id="updateBlog" parameterType="map" ><!--基本类型不用写resultType update里不需要-->
update mybatis.blog
<set>
<if test="title!=null">
title = #{title},
</if>
<if test="author!=null">
author = #{author}
</if>
</set>
where id = #{id}
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
<!--前缀覆盖什么 后缀覆盖什么-->
<trim prefix="" prefixOverrides="" suffix="" suffixOverrides="">
</trim>
</update>
IF
<select id="queryBlogIF" parameterType="map" resultType="blog">
<!--如果不传入title或者author 那么将执行select * from mybatis.blog where 1=1-->
select * from mybatis.blog where 1=1
<!--test必填 test里面写表达式:判断一些东西-->
<if test="title != null"><!--如果title不为空把这句话加上去-->
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
<!--例:如果穿了一个title和author去查询 sql会自动拼接为
select * from mybatis.blog WHERE title = ? and author = ?
传单个参数同理-->
优化
<!--需求:传title的时候按照title查 传author的时候按照author查 什么都不传查所有的-->
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<!--test必填 test里面写表达式:判断一些东西-->
<where>
<if test="title != null"><!--如果title不为空把这句话加上去-->
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
choose(when,otherwise)
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员精选的 Blog)。
<select id="queryBlogChoose" resultType="blog" parameterType="map">
select * from mybatis.blog
<where>
<choose>
<when test="title!=null">
title = #{title}<!--第一个语句不用加and 后面的要加 如果第一个不成立 由于有where的存在 会自动把and去掉-->
</when>
<when test="author!=null">
and author = #{author}
</when>
<otherwise>
and views = #{views}<!--如果两个条件都不成立执行这个-->
</otherwise>
</choose>
</where>
</select>
<!--=====================================================================================-->
<!--不加where 如果没有匹配的条件,最终SQL会变成
SELECT * FROM BLOG WHERE会导致查询失败
比如如果匹配的只是第二个条件 SQL会变成
SELECT * FROM BLOG WHERE AND title like ‘someTitle’
这个查询也会失败 这个问题不能简单地用条件元素来解决
MyBatis 有一个简单且适合大多数场景的解决办法
而这,只需要一处简单的改动 加where-->
select * from mybatis.blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
trim(where,set)
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)
<update id="updateBlog" parameterType="map" ><!--基本类型不用写resultType update里不需要-->
update mybatis.blog
<set>
<if test="title!=null">
title = #{title},
</if>
<if test="author!=null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
<!--sql会自动拼接为:
update mybatis.blog SET title = ?, author = ? where id = ?-->
2.1动态SQL:if+where 语句
<select id="selectUserByUsernameAndSex" resultType="User" parameterType="User">
select * from user
<where>
<if test="username != null">
and username=#{username}
</if>
<if test="sex != null">
and sex=#{sex}
</if>
</where>
</select>
2.2 动态SQL:choose(when,otherwise) 语句 (了解)
<select id="selectUserByChoose" resultType="User" parameterType="User">
select * from user
<where>
<choose>
<when test="id !='' and id != null">
and id=#{id}
</when>
<when test="username !='' and username != null">
and username=#{username}
</when>
<otherwise>
and sex=#{sex}
</otherwise>
</choose>
</where>
</select>
2.3 动态SQL:trim 语句 (了解)
<select id="selectUserByUsernameAndSex" resultType="user" parameterType="User">
select * from user
<trim prefix="where" prefixOverrides="and | or">
<if test="username != null">
and username=#{username}
</if>
<if test="sex != null">
and sex=#{sex}
</if>
</trim>
</select>
<!-- 根据 id 更新 user 表的数据 -->
<update id="updateUserById" parameterType="User">
update user u
<trim prefix="set" suffixOverrides=",">
<if test="username != null and username != ''">
u.username = #{username},
</if>
<if test="sex != null and sex != ''">
u.sex = #{sex},
</if>
</trim>
where id=#{id}
</update>