动态SQL
动态SQL语句就是指根据不同的条件(参数)生成不同的SQL语句!
我们可以进入官方文档进行查看:https://mybatis.org/mybatis-3/zh/dynamic-sql.html
可以看到其实只有四个标签
if
choose (when, otherwise)
trim (where, set)
foreach
接下来我们使用这些标签来编写动态SQL并进行测试!
新建项目
首先创建一个数据库!
CREATE DATABASE IF NO EXISTS `mybatis`;
USE `mybatis`;
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、编写配置文件;
前两步参考这篇博客:https://www.cnblogs.com/lmx-181028/p/12332861.html
3、编写blog实体类;
package com.star.pojo;
import java.util.Date;
import java.lombok.Data;
@Data
public class Blog {
private String id;
private String title;
private String author;
private Date createDate;
private int views;
}
可以看到字段createDate和create_time不对应
在数据库中我们一般使用下划线分割命名!
在Java中一般使用驼峰命名!
所以在官方文档中点击xml配置,点击settings,来进行转换!
在配置文件的
<settings>
<!--开启日志和驼峰命名转换-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
4、编写实体类对应的接口
package com.star.mapper;
import com.star.pojo.Blog;
import java.util.List;
import java.util.Map;
public interface BlogMapper {
//插入方法
int insertBlog(Blog blog);
}
5、编写Mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.star.mapper.BlogMapper">
</mapper>
我们给博客插入四条数据
<insert id="insertBlog" parameterType="Blog">
insert into `blog` (id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createDate},#{views});
</insert>
package com.star.mapper;
import com.star.pojo.Blog;
import com.star.utils.MybatisUtils;
import org.junit.Test;
import java.util.*;
public class BlogMapperTest {
@Test
public void insertBlogTest(){
BlogMapper mapper = MybatisUtils.getSession(true).getMapper(BlogMapper.class);
Blog blog1 = new Blog("1", "mybatis so easy", "lmx", new Date(), 999);
Blog blog2 = new Blog("2", "mybatis so easy", "aa", new Date(), 999);
Blog blog3 = new Blog("3", "mybatis so easy", "lmx", new Date(), 999);
Blog blog4 = new Blog("4", "mybatis so easy", "bb", new Date(), 999);
mapper.insertBlog(blog1);
mapper.insertBlog(blog2);
mapper.insertBlog(blog3);
mapper.insertBlog(blog4);
}
}
测试结果:
IF的使用
接口中添加方法
List<Blog> getBlogByIf(Map map)
通过作者名和博客名来查询博客,如果作者名字为null则通过博客名字来查询
<!--
如果我们需要拼接where条件,又不希望客户端传递的错误信息(不插入参数时,where就会报错),需要更加智能的where标签
如果有后面的语句,就自动添加where,如果后面语句开头时and或者or,它可以自动去掉
-->
<select id="getBlogByIf" resultType="Blog" parameterType="map">
select * from blog
<where>
<if test="title!=null">
title = #{title}
</if>
<if test="author!=null">
and author = #{author}
</if>
</where>
</select>
测试代码
@Test
public void getBlogByIf(){
BlogMapper mapper = MybatisUtils.getSession(false).getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<String, String>();
//这里我们只插入一个参数title
map.put("title","mybatis so easy");
List<Blog> blogByIf = mapper.getBlogByIf(map);
for (Blog blog : blogByIf) {
System.out.println(blog);
}
}
测试结果:
通过日志信息可以看到,实际的sql语句,并没有author,由于我们没有插入author参数,即为空所以不显示!
select * from blog WHERE title = ?
而当我们插入author参数时
map.put("author","lmx");
测试结果
实际的sql语句为
select * from blog WHERE title = ? and author = ?
对比两条sql语句,我们可以明显的看到不同的参数生成不同的SQL
这就是动态SQL语句!
set的使用
接口中添加方法
int updateBlog(Map map);
<!--
set,如果里面的条件满足,自动拼接
后面如果有多余的逗号,可以自动去除!
-->
<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}
</where>
</update>
@Test
public void updateBlogTest(){
BlogMapper mapper = MybatisUtils.getSession(true).getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
map.put("id","2");
map.put("title","Java so easy");
mapper.updateBlog(map);
}
测试结果:
sql语句:
update mybatis.blog SET title = ? WHERE id = ?
由于没有author参数,所以不显示!
map.put("author","cc");
测试结果:
sql语句:
update mybatis.blog SET title = ? ,author = ? WHERE id = ?
对比可见,动态sql非常智能,会去掉逗号!
trim的使用
where和set的底层其实都是trim
将上面的例子的set标签可以改为
<trim prefix="SET" suffixOverrides=",">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
author = #{author}
</if>
</trim>
可以看出由于有suffixOverrides,不用在author前加逗号,同理,where的参数前不用加and!
choose的使用
接口中添加方法
List<Blog> queryBlogChoose(Map map);
<!--
choose好比Java中的switch
case 1 --》when
case 2 --》when
default --》otherwise
-->
<select id="queryBlogChoose" parameterType="Blog">
select * from mybatis.blog
<where>
<choose>
<when test="title!=null">
title=#{title}
</when>
<when test="author!=null">
and title=#{title}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
@Test
public void queryBlogChoose(){
BlogMapper mapper = MybatisUtils.getSession(true).getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
}
测试结果:
sql语句
select * from mybatis.blog WHERE views = ?
@Test
public void queryBlogChoose(){
BlogMapper mapper = MybatisUtils.getSession(true).getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
map.put("title","MyBatis so easy");
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
}
测试结果:
sql的语句
select * from mybatis.blog WHERE title=?
@Test
public void queryBlogChoose(){
BlogMapper mapper = MybatisUtils.getSession(true).getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
map.put("title","MyBatis so easy");
map.put("author","aa");
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
}
测试结果:
sql的语句
select * from mybatis.blog WHERE title=?
对比这三次的测试结果,可以得出choose九好比于Java中的switch(只选择一项)
foreach
List<Blog> queryBlogForeach(Map map);
<!--sql() 子查询 where in (1,2,3)
collection 输入的参数map
item 遍历出来的每一项,可以在foreach标签中使用
-->
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="(" close=")" separator="or">
id = #{id}
</foreach>
</where>
</select>
@Test
public void testForeach(){
BlogMapper mapper = MybatisUtils.getSession(true).getMapper(BlogMapper.class);
Map<String, List> map = new HashMap<String, List>();
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
map.put("ids",list);
mapper.queryBlogForeach(map);
}
测试结果:
sql语句:
select * from mybatis.blog WHERE ( id = ? or id = ? or id = ? )
可以看出foreach声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
以上就是动态SQL语句,我们可以在官方文档中在深入理解!