动态SQL
1相关知识
-
什么是动态SQL:动态SQL就是根据不同的条件生成不同的SQL语句。
-
痛点:你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。
-
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。
-
在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
-
if
choose (when, otherwise)
trim (where, set)
foreach
2搭建环境
新建一个表
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8
创建一个基础工程
1.导包
2.编写配置文件
3.编写实体类
@Data
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;
private int views;
}
4.编写实体类对应的Mapper接口和Mapper.xml文件
3.动态SQL之IF语句
BlogMapper.xml
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title =#{title}
</if>
<if test="author !=null">
and author=#{author}
</if>
</select>
4.choose (when, otherwise)
<select id="queryBlogChoose" resultType="blog" parameterType="map">
select * from mybatis.blog
<where>
<choose>
<when test="title!=null">
title = #{title}
</when>
<when test="author!=null">
and author = #{author}
</when>
<otherwise>
and views=#{views}
</otherwise>
</choose>
</where>
</select>
when语句类似于switch,break.当有title和author时只选择title.
5.trim(where,set)
select * from mybatis.blog
<where>
<if test="title != null">
and title =#{title}
</if>
<if test="author !=null">
and author=#{author}
</if>
</where>
用where标签替代where 1=1
<update id="updateBlog" parameterType="map" >
update mybatis.blog
<set>
<if test="title!=null">
title = #{title},
</if>
<if test="author !=null">
author =#{author}
</if>
</set>
where id = #{id}
</update>
动态SQL的本质依然为SQL语句,只是我们可以在SQL层面执行一些逻辑代码
6.SQL片段
有时候,我们可能将一些功能的部分抽取出来,方便复用
①使用SQL标签抽取公共部分
<sql id="if-title-author">
<if test="title!=null">
title = #{title}
</if>
<if test="author !=null">
author =#{author}
</if>
</sql>
②在需要的地方使用include标签引用即可
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
注意事项:
- 最好基于单表来定义SQL片段
- 不要存在where标签
7.Foreach
对一个集合进行遍历,通常是在构造IN语句时候使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BAfd02gq-1631864736775)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210914144856343.png)]![](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210914144856584.png
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach></select>例子:(id=1 or id=2 or id =3)集合的名字为ids,集合的每一项为id,分隔符为or <foreach item="id" collection="ids" open="(" separator="or" close=")"> #{id} </foreach>
mapper.xml
<!-- select * from mybatis.blog where 1=1 and (id=1 or id=2 or id=3) 注意and后有空格 传递万能的map,map中存在一个集合 --> <select id="queryBlogForeach" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <foreach item="id" collection="ids" open="and (" separator="or" close=")"> id=#{id} </foreach> </where> </select>
测试
@Test public void queryBlogForeach(){ SqlSession sqlSession =MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); ArrayList<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); ids.add(3); map.put("ids",ids); List<Blog> blogs = mapper.queryBlogForeach(map); for(Blog blog :blogs){ System.out.println(blog); } sqlSession.close(); }
动态SQL就是在拼接SQL语句,保证SQL的正确性,按照SQL的格式,排列组合
建议
- 先写SQL语句,再对应去修改成为我们的SQL语句实现通用即可。