Mybatis3-04-动态SQL

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();
    }

输出结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值