动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
Mybatis动态 SQL:https://mybatis.org/mybatis-3/zh/dynamic-sql.html
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
从例子开始
数据库内容
实体类,与数据库相对应,只是createTime字段与数据库(create_time)不同,为了在查询数据时不出错,需要在配置文件中添加一下设置
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
准备工作就这么多,当然还有必要的Mybatis的配置。
1.往数据库中插入多条数据
根据之前的只是,只能一行一行的往里插入:
<insert id="insert" parameterType="Blog">
insert into blog(id,title,author,create_time,views) value (#{id},#{title},#{author},#{createTime},#{views});
</insert>
如果要插入多条就用到了动态sql中的,foreach:
接口方法
void insertMore(List<Blog> blogs);
于是insert语句变成了这样
<insert id="insertMore" parameterType="list">
insert into blog(id,title,author,create_time,views) value
<foreach collection="list" item="blog" separator=",">
(#{blog.id},#{blog.title},#{blog.author},#{blog.createTime},#{blog.views})
</foreach>
</insert>
他生成的sql语句是:insert into blog(id,title,author,create_time,views) value (?,?,?,?,?),(?,?,?,?,?),(?,?,?,?,?)......
介绍一下foreach标签中的属性:
foreach就是遍历集合, 即遍历传过来的参数。
- item:每次遍历生成的对象,该参数为必选。
- index:在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选
- open:foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选
- separator:元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
- close: foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
- collection: List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键,map一般都是我们手动设置键。
详细参考:https://www.cnblogs.com/fnlingnzb-learner/p/10566452.html
插入数据测试代码:
Blog b1 = new Blog("5","老张怎么这么美","老张",new Date(),11111);
Blog b2 = new Blog("6","老张美极了","老张",new Date(),98888);
List<Blog> blogs = new ArrayList<Blog>();
blogs.add(b1);
blogs.add(b2);
mapper.insertMore(blogs);
sqlSession.commit();
2.根据条件查询
之前我们只能写固定的查询条件:
select * from blog where author = '老张' and title = '老张非常美'
但是根据动态sql我们可以写可有可无的条件,就是说后边的查询条件加不加都可以查出数据:
此时<select>标签变成了这样
<select id="select" parameterType="map" resultType="Blog">
select * from blog
<where>
<if test="author!=null">
author = #{author}
</if>
<if test="title!=null">
and title = #{title}
</if>
</where>
</select>
<if>标签:只有一个属性test,里边写条件
<where>标签:如果where标签中的条件成立,也就是有查询条件,那么就会在原来的sql后加上where,如果where标签里的内容不成立,就不会加上where,Mybatis会帮我们自动拼接sql,并且如果第一个if标签不成立,那么第二个if标签里的and会被删去,反之,不删。传参用的是map集合,所以条件用的都是键的值。
测试代码:
Map<String,Object> map = new HashMap();
map.put("title","老张非常美");
map.put("author","小张");
List<Blog> blog = mapper.select(map);
System.out.println(blog);
3.如果说作者是"老张"或者"小张",都可以怎么办?
于是它变成了这样
<select id="selectByAuthorsAndTitle" parameterType="map" resultType="Blog">
select * from blog
<where>
<foreach collection="authors" item="author" separator="or" open="(" close=")">
author=#{author}
</foreach>
<if test="title!=null">
and title=#{title}
</if>
</where>
</select>
测试代码:
Map<String,Object> map = new HashMap();
List<String> list = new ArrayList<String>();
list.add("老张");
list.add("小张");
map.put("authors",list);
map.put("title","老张非常美");
mapper.selectByAuthorsAndTitle(map);
List<Blog> blog = mapper.select(map);
此时终于明白了collection标签的真正含义, collection="authors",authors是map中键的名字,因为key是一个list集合所以用foreach遍历它,而开头的collection="list"是list集合默认的名字,因为这里指定了键名所以不能用默认的名字了。
4.choose (when, otherwise)
它和java中的switch差不多,只能选择一个条件执行,when中的条件不成立的话,选择otherwise执行。
5.trim标签官网也没有太多介绍
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。
文章内容参考:https://mp.weixin.qq.com/s/gtXsTG2naMTDnC6aqQICMg