【视频 & 交流平台】
http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=400000000155061&utm_medium=share
http://study.163.com/course/introduction.htm?courseId=1004638001&utm_campaign=commission&utm_source=400000000155061&utm_medium=share
https://gitee.com/happyangellxq520/spring-boot
http://412887952-qq-com.iteye.com/blog/2321532
需求缘起:
对于XML配置方法大家比较熟悉,为了文章系列的完整性,在这里也简单的介绍下。
本章的大纲:
(2)if+where的条件判断
(3)if+set的更新语句
(4)if+trim代替where/set标签
(5)choose (when, otherwise)
(6)foreach
接下来看下具体的内容:
(1)if标签
if标签可用在许多类型的sql语句中,我们以查询为例。首先看一个很普通的查询:
<select id="select1" resultMap="baseResultMap"> select *from demo where name = #{name} and email = #{email} </select>
但是此时如果name或email为null,此语句很可能报错或查询结果为空。此时我们使用if动态sql语句先进行判断,如果值为null或等于空字符串,我们就不进行此条件的判断,增加灵活性。
DemoMapper的代码很简单:
/**test if */ public List<Demo> select1(Demo demo);
Demo.xml代码修改为使用if test:
<select id="select1" resultMap="baseResultMap"> select *from demo where <if test="name != null and name != ''"> name = #{name} </if> <if test="email != null and email != ''"> and email=#{email} </if> </select>
访问http://127.0.0.1:8080/select1?name=王五 能正常访问,
但是如果访问:
http://127.0.0.1:8080/select1 或者 http://127.0.0.1:8080/[email protected]
一运行就报错了。这时候where标签就出现了,所以技术就有存在的道理。
(2)if+where的条件判断
当where中的条件使用的if标签较多时,这样的组合可能会导致错误。上面的查询语句中,当访问:http://127.0.0.1:8080/[email protected] 参数name为null,将不会进行name列的判断,则会直接导“WHERE AND”关键字多余的错误SQL。
这时我们可以使用where动态语句来解决。这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。
上面的<select>修改为如下:
<select id="select1" resultMap="baseResultMap"> select *from demo <where> <if test="name != null and name != ''"> name = #{name} </if> <if test="email != null and email != ''"> and email=#{email} </if> </where> </select>
此时访问的话,会构造不同的SQL语句:
访问1:http://127.0.0.1:8080/select1
select *from demo
访问2:http://127.0.0.1:8080/select1?name=王五
select *from demo WHERE name = ?
访问3:http://127.0.0.1:8080/[email protected]
select *from demo WHERE email=?
访问5:http://127.0.0.1:8080/select1?name=王五&[email protected]
select *from demo WHERE name = ? and email=?
都非常的完美。
(3)if+set的更新语句
当update语句中没有使用if标签时,如果有一个参数为null,都会导致错误。
当在update语句中使用if标签时,如果前面的if没有执行,则会导致逗号多余错误。使用set标签可以将动态的配置SET 关键字,和剔除追加到条件末尾的任何不相关的逗号。
使用if+set标签修改后,如果某项为null则不进行更新,而是保持数据库原值。如下示例:
<update id="update1"> update demo <set> <if test="name != null and name != ''"> name = #{name}, </if> <if test="email != null and email != ''"> email=#{email} </if> </set> where id = #{id} </update>
这样就可以单独修改name或者email,或者是同时修改name和email,但是需要注意,如果什么都不修改的话是会报错的。
(4)if+trim代替where/set标签
trim是更灵活的去处多余关键字的标签,它可以实践where和set的效果。
(4.1)trim 代替where
<select id="select2" resultMap="baseResultMap"> select *from demo <trim prefix="where" prefixOverrides="and|or"> <if test="name != null and name != ''"> name = #{name} </if> <if test="email != null and email != ''"> and email=#{email} </if> </trim> </select>
(4.1)trim 代替set
<update id="update2"> update demo <trim prefix="set" suffixOverrides=","> <if test="name != null and name != ''"> name = #{name}, </if> <if test="email != null and email != ''"> email=#{email} </if> </trim> where id = #{id} </update>
(5)choose (when, otherwise)
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。而使用if标签时,只要test中的表达式为true,就会执行if标签中的条件。MyBatis提供了choose 元素。if标签是与(and)的关系,而choose标签是或(or)的关系。
choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。
例如下面例子,同样把所有可以限制的条件都写上,方面使用。choose会从上到下选择一个when标签的test为true的sql执行。安全考虑,我们使用where将choose包起来,放置关键字多于错误。
<select id="select3" resultMap="baseResultMap"> select *from demo <where> <choose> <when test="name != null and name != ''"> name = #{name} </when> <when test="email != null and email != ''"> and email=#{email} </when> <otherwise> </otherwise> </choose> </where> </select>
访问测试:
访问1:http://127.0.0.1:8080/select3
select *from demo
访问2:http://127.0.0.1:8080/select3?name=王五
select *from demo where name = ?
访问3:http://127.0.0.1:8080/[email protected]
select *from demo WHERE email = ?
访问4:http://127.0.0.1:8080/select3?name=王五&[email protected]
select *from demo WHERE name = ?
这里满足了name != null and name != ''的条件,所以条件就是name=?。
(6)foreach
对于动态SQL 非常必须的,主是要迭代一个集合,通常是用于IN 条件。List 实例将使用“list”做为键,数组实例以“array” 做为键。
foreach元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。
注意:你可以传递一个List实例或者数组作为参数对象传给MyBatis。当你这么做的时候,MyBatis会自动将它包装在一个Map中,用名称在作为键。List实例将会以“list”作为键,而数组实例将会以“array”作为键。
(6.1)参数为array示例的写法
接口方法的声明:
/**foreach: 参数为array示例的写法*/ public List<Demo> select3(String[] ids);
动态SQL语句:
<select id="select4" resultMap="baseResultMap"> select *from demo where id in <foreach collection="array" item="id" open="(" separator="," close=")"> #{id} </foreach> </select>
(6.2)参数为List示例的写法
接口方法声明:
/**foreach: 数为list示例的写法*/ public List<Demo> select5(List<Integer> list);
动态SQL语句:
<select id="select5" resultMap="baseResultMap"> select *from demo where id in <foreach collection="list" item="id" open="(" separator="," close=")"> #{id} </foreach> </select>
视频&交流平台:
http://study.163.com/course/introduction.htm?courseId=1004329008
http://412887952-qq-com.iteye.com/blog/2321532