Mybatis3-动态SQL_环境搭建_if语句_choose语句_set语句_Foreach语句_demo07
1 动态SQL之— 环境搭建
1.1 什么是动态SQL
动态SQL是根据不同的条件生成不同的SQL语句
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,
你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,
需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,
MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,
现在要学习的元素种类比原来的一半还要少。
if
choose (when, otherwise)
trim (where, set)
foreach
1.2 搭建环境
1.2.1 创建数据库表-blog(博客表)
CREATE TABLE `blog`(
id VARCHAR(50) NOT NULL COMMENT '博客id',
title VARCHAR(50) NOT NULL COMMENT '博客标题',
author VARCHAR(50) NOT NULL COMMENT '博客作者',
create_time DATETIME NOT NULL COMMENT '创建时间',
views INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8
1.2.2 创建一个基础工程
1.2.2.1 导包 lombok
<dependencies>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
1.2.2.2 编写核心配置文件 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置文件-->
<configuration>
<!--引入外部配置文件db.prperties-->
<properties resource="db.properties">
</properties>
<!--settings设置标准日志输出-->
<!--settings标签只能存在于properties标签和typeAliases标签之间-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!--开启驼峰命名转换-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--给实体类起别名-->
<typeAliases>
<package name="com.zzy.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--绑定接口-->
<mappers>
<mapper resource="mapper/BlogMapper.xml"/>
</mappers>
</configuration>
1.2.2.3 编写工具类 IDUtils
因为数据表中的id是主键,是不可重复的,使用UUID随机生成的数字作为主键
package com.zzy.utils;
import org.junit.Test;
import java.util.UUID;
@SuppressWarnings("all")//抑制警告
public class IDUtils {
public static String getId(){
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
return uuid;
}
@Test
public void testUUID(){
System.out.println(IDUtils.getId());
System.out.println(IDUtils.getId());
System.out.println(IDUtils.getId());
System.out.println(IDUtils.getId());
}
}
1.2.2.4 编写实体类 Blog
处理属性名称和字段名称不一致的配置
mapUnderscoreToCamelCase
是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
true | false
默认 False
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
package com.zzy.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias;
import java.util.Date;
@Alias("Blog")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
private String id;
private String title;
private String author;
private Date createTime;//字段名称 create_time 属性名称和字段名称不一致
private int views;
}
1.2.2.5 编写实体类对应的Mapper接口 和 Mapper.xml文件
写接口添加数据
package com.zzy.dao;
import com.zzy.pojo.Blog;
public interface BlogMapper {
//插入数据
int addBlog(Blog blog);
}
编写sql 注意:SQL中 #{createTime} 要和实体类中的属性名称匹配
<?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.zzy.dao.BlogMapper">
<insert id="addBlog" parameterType="Blog">
insert into mybatis.blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views})
</insert>
</mapper>
1.2.2.6 编写测试类-测试环境搭建状况
package com.zzy.test;
import com.zzy.dao.BlogMapper;
import com.zzy.pojo.Blog;
import com.zzy.utils.IDUtils;
import com.zzy.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.Date;
public class MyTest {
//测试插入博客数据
@Test
public void testInsertBlog(){
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(999);
mapper.addBlog(blog);
blog.setId(IDUtils.getId());
blog.setTitle("spring更难");
mapper.addBlog(blog);
blog.setId(IDUtils.getId());
blog.setTitle("ssm很简单");
mapper.addBlog(blog);
sqlSession.close();
}
}
1.2.2.7 输出结果
测试控制台的输出
数据库展示添加的数据
2 动态SQL之— if语句
2.1 创建接口方法
查询博客 动态if语句使用
//查询博客 动态if语句使用
List<Blog> queryBlogIF(Map map);
2.2 编写sql语句
<!--查询数据操作 动态if-->
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<if test="title != null ">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
2.3 测试四种情况
map中无值 ----查询得到所有表记录
map中传递title值----查询得到以title为条件的所有记录
map中传递author值----查询得到以author为条件的所有记录
map中传递title和author值----查询得到以title和author为条件的表记录
2.3.1 测试查询-map中无参数–输出结果
//动态SQL---if查询
@Test
public void testQueryBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
/*map中无值,表示查询的是全部*/
Map map = new HashMap();
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
查询得到全部数据库记录
2.3.2 测试查询-map中有title参数–输出结果
//动态SQL---if查询
@Test
public void testQueryBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
/*map中有title值,表示查询的是以title值为条件的记录*/
Map map = new HashMap();
map.put("title", "ssm很简单");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
查询得到以title值为条件的记录
2.3.3 测试查询-map中有author参数–输出结果
//动态SQL---if查询
@Test
public void testQueryBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
/*map中有title值,表示查询的是以title值为条件的记录*/
//map.put("title", "ssm很简单");
/*map中有author值,表示查询的是以author值为条件的记录*/
map.put("author","高斯林");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
查询得到以author值为条件的记录
2.3.4 测试查询-map中有title和author参数–输出结果
//动态SQL---if查询
@Test
public void testQueryBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
/*map中有title值,表示查询的是以title值为条件的记录*/
map.put("title", "ssm很简单");
/*map中有author值,表示查询的是以author值为条件的记录*/
map.put("author","高斯林");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
查询得到以title和author值为条件的记录
3 动态SQL之— choose(when、otherwise)语句–类似java的switch语句—查询操作
choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,
MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句
只能执行满足条件的某一种情况
3.1 编写接口方法-
package com.zzy.dao;
import com.zzy.pojo.Blog;
import java.util.List;
import java.util.Map;
public interface BlogMapper {
//插入数据
int addBlog(Blog blog);
//查询博客 动态if语句使用
List<Blog> queryBlogIF(Map map);
//查询博客 动态choose语句使用
List<Blog> queryBlogChoose(Map map);
}
3.2 编写SQL语句
<!--查询数据操作 动态choose-->
<select id="queryBlogChoose" parameterType="map" resultType="Blog">
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>
3.3 测试五种类情况
3.3.1 测试查询map中有title参数(otherwise中参数不变)
//动态SQL---choose when otherwise查询--相当于switch语句,只选择其中的一项
@Test
public void testQueryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
/*map中有title值,表示查询的是以title值为条件的记录*/
map.put("title", "ssm很简单");
/*map中有author值,表示查询的是以author值为条件的记录*/
//map.put("author","高斯林");
/*map中没有title并且没有author值,表示查询的是以views值为条件的记录*/
map.put("views", 999);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
测试结果
3.3.2 测试查询map中有author参数(otherwise中参数不变)
//动态SQL---choose when otherwise查询--相当于switch语句,只选择其中的一项
@Test
public void testQueryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
/*map中有title值,表示查询的是以title值为条件的记录*/
//map.put("title", "ssm很简单");
/*map中有author值,表示查询的是以author值为条件的记录*/
map.put("author","高斯林");
/*map中没有title并且没有author值,表示查询的是以views值为条件的记录*/
map.put("views", 999);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
测试结果
3.3.3 测试查询map中有title和author参数(otherwise中参数不变)
//动态SQL---choose when otherwise查询--相当于switch语句,只选择其中的一项
@Test
public void testQueryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
/*map中有title值,表示查询的是以title值为条件的记录*/
map.put("title", "ssm很简单");
/*map中有author值,表示查询的还是以满足第一个title值为条件的记录,只选择第一个条件
* title属性值条件得到匹配,那么author就不在匹配
* 查询出来的数据还是title为条件的结果*/
map.put("author","高斯林");
/*map中没有title并且没有author值,表示查询的是以views值为条件的记录*/
map.put("views", 999);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
测试结果
3.3.4 测试查询map中无其他参数,otherwise中有参数
//动态SQL---choose when otherwise查询--相当于switch语句,只选择其中的一项
@Test
public void testQueryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
/*map中有title值,表示查询的是以title值为条件的记录*/
//map.put("title", "ssm很简单");
/*map中有author值,表示查询的还是以满足第一个title值为条件的记录,只选择第一个条件
* title属性值条件得到匹配,那么author就不在匹配
* 查询出来的数据还是title为条件的结果*/
//map.put("author","高斯林");
/*map中没有title并且没有author值,表示查询的是以views值为条件的记录*/
map.put("views", 999);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
查询结果
3.3.5 测试查询map中没有参数,when和otherwise都没有条件
//动态SQL---choose when otherwise查询--相当于switch语句,只选择其中的一项
@Test
public void testQueryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
/*map中有title值,表示查询的是以title值为条件的记录*/
//map.put("title", "ssm很简单");
/*map中有author值,表示查询的还是以满足第一个title值为条件的记录,只选择第一个条件
* title属性值条件得到匹配,那么author就不在匹配
* 查询出来的数据还是title为条件的结果*/
//map.put("author","高斯林");
/*map中没有title并且没有author值,表示查询的是以views值为条件的记录*/
//map.put("views", 999);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
查询结果
4 动态SQL之— trim(where、set)语句—修改操作
4.1 编写接口方法
package com.zzy.dao;
import com.zzy.pojo.Blog;
import java.util.List;
import java.util.Map;
public interface BlogMapper {
//插入数据
int addBlog(Blog blog);
//查询博客 动态if语句使用
List<Blog> queryBlogIF(Map map);
//查询博客 动态choose语句使用
List<Blog> queryBlogChoose(Map map);
//修改操作
int updateBlog(Map map);
}
4.2 编写sql
<!--修改blog操作-->
<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>
4.3 测试四种情况
4.3.1 测试修改map中有title参数,根据id条件修改
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)
//动态SQL----修改blog信息
@Test
public void testUpdateBlogById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("title", "ssh比ssm难");
//map.put("author", "詹姆斯");
map.put("id", "61a41298568f471f83cf6135d4cac675");
int rows = mapper.updateBlog(map);
System.out.println(rows);
sqlSession.close();
}
测试结果
4.3.2 测试修改map中有author参数,根据id条件修改
//动态SQL----修改blog信息
@Test
public void testUpdateBlogById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
//map.put("title", "ssh比ssm难");
map.put("author", "詹姆斯1111");
map.put("id", "61a41298568f471f83cf6135d4cac675");
int rows = mapper.updateBlog(map);
System.out.println(rows);
sqlSession.close();
}
测试结果
4.3.3 测试修改map中有title和author参数,根据id条件修改
//动态SQL----修改blog信息
@Test
public void testUpdateBlogById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("title", "ssh比ssm难");
map.put("author", "詹姆斯");
map.put("id", IDUtils.getId());
int rows = mapper.updateBlog(map);
System.out.println(rows);
sqlSession.close();
}
测试结果
4.3.4 测试修改map中无title和author参数,根据id条件修改
//动态SQL----修改blog信息
@Test
public void testUpdateBlogById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
//map.put("title", "ssh比ssm难");
//map.put("author", "詹姆斯1111");
map.put("id", "61a41298568f471f83cf6135d4cac675");
int rows = mapper.updateBlog(map);
System.out.println(rows);
sqlSession.close();
}
测试结果
5 动态SQL之— SQL片段
有时候,需要将SQL中的一些公共部分抽取出来,方便复用
sql标签:用来抽取公共部分
include标签:在需要使用的地方使用include标签引用即可
注意事项:最好基于单表来定义SQL片段
不要存在where标签
<!--查询数据操作 动态if, sql标签提取公共部分-->
<sql id="if-title-author">
<if test="title != null ">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<include refid="if-title-author"></include><!--include标签引入进来-->
</where>
</select>
6 动态SQL之— Foreach
6.1 编写接口(批量查询)
package com.zzy.dao;
import com.zzy.pojo.Blog;
import java.util.List;
import java.util.Map;
public interface BlogMapper {
//插入数据 pojo属性名和字段名称不一致
int addBlog(Blog blog);
//查询博客 动态if语句使用
List<Blog> queryBlogIF(Map map);
//查询博客 动态choose语句使用
List<Blog> queryBlogChoose(Map map);
//修改操作,动态set语句使用
int updateBlog(Map map);
//批量查询操作 动态foreach语句使用
List<Blog> queryBlogForeach(Map map);
}
6.2 编写SQL
<!--批量查询操作-->
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id = #{id}
</foreach>
</where>
</select>
6.3 执行查询输出结果
//动态SQL----foreach语句
@Test
public void testQueryBlogForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
ArrayList<Integer> ids = new ArrayList<>();
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();
}
输出结果