引用文档
动态 SQL
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
主要的标签如下:
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
在实际的开发中,查询可能是多条件的,比如可能只有姓名,可能只有性别,可能有性别和姓名,
然后这些条件可以组成一个对象,根据对象包含的属性进行条件查询
mysql创建数据库
create database rainbow; use rainbow; CREATE TABLE `user` ( `uid` int(11) NOT NULL auto_increment, `name` varchar(32) NOT NULL COMMENT '用户名称', `sex` char(1) default NULL COMMENT '性别', `addr` varchar(256) default NULL COMMENT '地址', PRIMARY KEY (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1. if,也就是判断语句
test 属性中写的是对象的属性名,构成一个判断语句
在下面的案例中,where 1= 1,是为了拼接sql语句
如果没有1 = 1,再name为空的情况下,查询语句就变成了
select * from user where and sex = ?
<select id="findByIf" resultType="user" parameterType="user"> select * from user where 1 = 1 <if test="name != null"> and name like #{name} </if> <if test="sex != null"> and sex = #{sex} </if> </select> 如果没有 1= 1 ,代码就会变成这样 <select id="findByIf" resultType="user" parameterType="user"> select * from user where <if test="name != null"> name like #{name} </if> <if test="sex != null"> and sex = #{sex} </if> </select>
2. where
为了简化上面 where 1=1 的条件拼装,我们可以采用<where>标签来简化开发
如果任何条件都不成立,那么就在sql语句里就不会出现where关键字
如果有任何条件成立,会自动去掉多出来的 and 或者 or
<select id="findByWhere" resultType="user" parameterType="user"> select * from user <where> <if test="name != null"> name like #{name} </if> <if test="sex != null"> and sex = #{sex} </if> </where> </select>
3. set
与where类似的,在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:
其效果与where标签类似,有数据的时候才进行设置,它会自动将多余的逗号(,)去掉。
<update id="updateUser" parameterType="user"> update user <set> <if test="name != null"> name = #{name}, </if> <if test="sex != null"> sex = #{sex}, </if> <if test="addr != null"> addr = #{addr} </if> </set> where uid = #{uid} </update>
4. trim
自定义功能
trim 用来定制想要的功能,比如where和set标签都可以用trim来替换
下面是它涉及到的属性与解释
示例,这个与上面的where实现的效果是一样的
<select id="findByTrim" resultType="user" parameterType="user"> select * from user <trim prefix="where" prefixOverrides="and"> <if test="name != null"> name like #{name} </if> <if test="sex != null"> and sex = #{sex} </if> </trim> </select>
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。
<select id="findByChoose" resultType="user" parameterType="user"> select * from user <where> <choose> <when test="name != null"> name like #{name} </when> <when test="sex != null"> and sex = #{sex} </when> <otherwise> and uid > 5 </otherwise> </choose> </where> </select>
6. foreach
oreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名;
index指定一个名字,用于表示在迭代过程中,每次迭代到的位置;
open表示该语句以什么开始;
separator表示在每次进行迭代之间以什么符号作为分隔符;
close表示以什么结束;
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:
如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
<!-- select * from user where id in (1,2,3,4,5); --> <select id="findInIds" parameterType="uservo" resultType="user"> select * from user <where> <if test="ids != null and ids.size() > 0"> uid in <foreach collection="ids" open="(" close=")" item="uid" separator=","> #{uid} </foreach> </if> </where> </select> 另UserVo是User的封装类 public class UserVo { private List<Integer> ids; public List<Integer> getIds() { return ids; } public void setIds(List<Integer> ids) { this.ids = ids; } }
7. sql片段
有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
提取sql片段
<sql id="if-name-sex"> <if test="name != null"> name like #{name} </if> <if test="sex != null"> and sex = #{sex} </if> </sql>
引用sql片段
<select id="findByWhere" resultType="user" parameterType="user"> select * from user <where> <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace --> <include refid="if-name-sex"/> <!-- 在这里还可以引用其他的 sql 片段 --> </where> </select>
注意:
①、最好基于 单表来定义 sql 片段,提高片段的可重用性
②、在 sql 片段中不要包括 where
小结:
其实动态 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,
我们最好首先要写原生的 sql 语句出来,然后在通过 mybatis 动态sql 对照着改,防止出错。
多在实践中使用才是熟练掌握它的技巧
以下是trim标签中涉及到的属性:属性描述prefix给sql语句拼接的前缀suffix给sql语句拼接的后缀prefixOverrides去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND"suffixOverrides去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定————————————————版权声明:本文为CSDN博主「wt_better」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/wt_better/article/details/80992014