一:动态SQL 概念
动态SQL就是指根据不同的条件生成不同的SQL语句
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
-
if
提供了可选的查找文本功能
-
choose (when, otherwise) 从多个条件中选择一个使用
传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG
-
trim (where, set)
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)
-
foreach
二:动态SQL 环境搭建
1、新建模块 (导入依赖)
<dependencies>
<!-- Lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
2、编写配置文件
3、新建数据库表
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
4、编写实体类
import lombok.Data;
import java.util.Date;
@Data
public class Blog {
private String id; //博客id
private String title; //博客标题
private String author; //博客作者
private Date createTime; //创建时间
// 属性名和字段名不一致 开启驼峰命名映射 在核心配置文件中配置mapUnderscoreToCamelCase
private int views; //浏览量
}
5、编写实体类对应的Mapper接口 和 Mapper.xml文件
Mapper接口
public interface BlogMapper {
}
Mapper.xml文件
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.csnz.dao.BlogMapper">
</mapper>
6、在mybatis核心配置文件中对Mapper进行注册
7、新建一个随机生成id的工具类
import java.util.UUID;
public class IDUtils {
public static String getId(){
return UUID.randomUUID().toString().replace("-","");
}
}
8、目前数据库表中无数据 插入数据
最后新建一个测试类测试一波~
public class TestBlog {
@Test
public void testInsert(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IDUtils.getId());
blog.setTitle("潮汕奴仔学Mybatis");
blog.setAuthor("潮汕奴仔");
blog.setCreateTime(new Date());
blog.setViews(666);
mapper.add(blog);
sqlSession.close();
}
}
接下来大家可以照猫画虎多插几条数据进去
三、尝试编写动态SQL
1、If
<!--根据条件查询-->
<select id="queryByIf" parameterType="map" resultType="blog">
select * from blog where 1 = 1
<if test="title != null">
AND title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
测试:
@Test
public void testIf(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
// map.put("title","潮汕奴仔学Mybatis");
map.put("author","CSNZ");
List<Blog> blogs = mapper.queryByIf(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
2、trim ( where、set )
where
<!--根据条件查询 if -->
<select id="queryByIf" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
set
<!--根据条件 更新 set-->
<update id="updateBySet" parameterType="map">
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
对应的测试demo
@Test
public void testUpdateSet(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
// map.put("title","奴仔学Vue");
map.put("author","HaibaraAi");
map.put("id","830344215782422b89dfdfd2cac008b2");
mapper.updateBySet(map);
sqlSession.close();
}
3、choose ( when , otherwise )
<!--根据条件查询 choose-->
<select id="queryByChoose" parameterType="map" resultType="blog">
select * from 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>
对应的测试demo
@Test
public void testChoose(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("title","潮汕奴仔学Vue");
map.put("author","CSNZ");
map.put("views",1000);
List<Blog> blogs = mapper.queryByChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
总结:
动态SQL的实质还是一个SQL ,只是我们可以 在编写 sql 时,执行逻辑判断
四:SQL片段
思想:封装代码 ,方便复用
1、使用sql 标签抽取公共的部分
<!--SQL片段-->
<sql id="if-title-author">
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</sql>
2、在需要使用的地方使用include标签引用
注意事项:
五:foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候
官网案例
<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>
foreach 元素的功能:
指定一个集合,可以在元素体内使用的集合项(item)和索引(index)变量。
它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。
下面开始编写测试代码
先测试空的集合 会发生肾么丝!
@Test
public void testForEach(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
ArrayList ids = new ArrayList();
Map map = new HashMap();
map.put("ids",ids);
mapper.getBlogsByForEach(map);
sqlSession.close();
}
亚巴里~ 查询了全部
接下来我们给ids集合添加元素试试
@Test
public void testForEach(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
ArrayList ids = new ArrayList();
ids.add("0d1df68b89604b4d9c8ca0233d4dc20e");
ids.add("95d317d5401e44c8bbba8cb07a3a2d41");
ids.add("1d4a10e260264050a77e810d0bd2e11c");
Map map = new HashMap();
map.put("ids",ids);
mapper.getBlogsByForEach(map);
sqlSession.close();
}