• 动态SQL



    学习视频来自于:秦疆(遇见狂神说)Bilibili地址
    他的自学网站:kuangstudy

    你只有走完必须走的路,才能过想过的生活


    一、动态SQL

    1.1 介绍

    什么是动态SQL:动态SQL就是 指根据不同的条件生成不同的SQL语句
    利用动态SQL这一特性可以彻底摆脱这种痛苦。

    MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

    if
    choose (when, otherwise)
    trim (where, set)
    foreach

    1.2 环境搭建

    sql

    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 '浏览量'
    	PRIMARY KEY(`id`)
    )ENGINE=INNODB DEFAULT CHARSET=utf8
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实体类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Blog {
        private String id;
        private String title;
        private String author;
        private Date createTime;
        private int views;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    字段名不一致
    数据库是create_time
    实体类是createTime
    在mybatis配置文件可以通过settings设置

    设置名描述有效值默认值
    mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true、falseFalse
    <settings>
       <setting name="mapUnderscoreToCamelCase" value="true"/>
    settings>
    
    • 1
    • 2
    • 3

    BlogMapper.java

    public int addBlog(Blog blog);
    
    • 1

    BlogMapper.xml

    <insert id="addBlog" parameterType="blog">
        insert into blog (id, title, author, create_time, views)
        values (#{id},#{title},#{author},#{createTime},#{views});
    insert>
    
    • 1
    • 2
    • 3
    • 4

    添加数据

    @Test
    public void andBlog(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
        Blog blog1 = new Blog(UUidutil.getUUID(),"Mybatis如此简单","狂神过",new Date(),9999);
        mapper.addBlog(blog1);
        sqlSession.commit(); // 没有开启自动提交,需要手动提交
    
        Blog blog2 = new Blog(UUidutil.getUUID(),"Java如此简单","狂神过",new Date(),9999);
        mapper.addBlog(blog2);
        sqlSession.commit();
    
        Blog blog3 = new Blog(UUidutil.getUUID(),"Spring如此简单","狂神过",new Date(),1000);
        mapper.addBlog(blog3);
        sqlSession.commit();
    
        Blog blog4 = new Blog(UUidutil.getUUID(),"微服务如此简单","狂神过",new Date(),9999);
        mapper.addBlog(blog4);
        sqlSession.commit();
    
        System.out.println("添加成功");
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    1.3 if语句

    BlogMapper.java

    public List<Blog> queryBlogByTitleByAuthor(Map<String, String> map);
    
    • 1

    BlogMapper.xml

    <select id="queryBlogByTitleByAuthor" resultType="blog" parameterType="map">
        select * from blog where 1=1
        <if test="title != null">
            and title = #{title}
        if>
        <if test="author != null">
            and author = #{author}
        if>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试

    @Test
    public void queryBlogByTitleByAuthor(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String, String> map = new HashMap<>();
        map.put("title","Java如此简单");
        for (Blog blog : mapper.queryBlogByTitleByAuthor(map)) {
            System.out.println(blog);
        }
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.4 常用标签

    choose
    java中的switch语句

    <select id="queryBlogByTitleByAuthor" resultType="blog" parameterType="map">
        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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    where
    帮助SQL中智能的结合语句添加删除and、or,更多功能可以使用自定义trim。

    <select id="queryBlogByTitleByAuthor" resultType="blog" parameterType="map">
        select * from blog
        <where>
            <if test="title != null">
                and title = #{title}
            if>
            <if test="author != null">
                and author = #{author}
            if>
        where>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    set
    自动添加set,删除无关的逗号
    BlogMapper.java

    int updateBlog(Map map);
    
    • 1

    BlogMapper.xml

    <update id="updateBlog" parameterType="map">
        update blog
        <set>
            <if test="title != null">title = #{title},if>
            <if test="author != null">author = #{author},if>
            <if test=" createTime != null">create_time = #{createTime},
            if>
            <if test="views != null">views = #{views}if>
        set>
        where id = #{id};
    update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    测试

        @Test
        public void updateBlog(){
            SqlSession sqlSession = MybatisUtil.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
            HashMap<String, Object> map = new HashMap<>();
            map.put("id","9fa1a8b147394d6db3aa480189f3ecba");
            map.put("title","简单");
            mapper.updateBlog(map);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码

    1.5 SQL片段

    有的时候,我们可以能会将一些功能的部分抽取出来,方便复用!

    使用SQL标签抽取公共的部分

    <sql id="if-title-author-views">
        <if test="title != null">title = #{title}if>
        <if test="author != null">and author = #{author}if>
        <if test="views != null" > and views = #{views}if>
    sql>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在需要使用的地方使用Include标签引用即可

    <select id="queryBlogByTitleByAuthor" resultType="blog" parameterType="map">
        select * from blog
        <where>
            <include refid="if-title-author-views">include>
        where>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意事项

    1. 最好基于单表来定义SQL片段!
    2. 不要存在where标签

    1.6 Foreach

    1. 动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。
    2. foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
    3. 提示你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

    BlogMapper.java

    public List<Blog> queryBlogByid(Map map);
    
    • 1

    BlogMapper.xml

    
    <select id="queryBlogByid" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <foreach collection="ids" item="id" open="(" separator="or" close=")">
                id = #{id}
            foreach>
        where>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    测试

    @Test
    public void queryBlogByid(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String, List> map = new HashMap<>();
        ArrayList<String> list = new ArrayList<>();
        list.add("0a547141ea664a438268c8f20e5dd049");
        list.add("0e4cd725e18549cca0fb7fba317fb82a");
        map.put("ids",list);
        for (Blog blog : mapper.queryBlogByid(map)) {
            System.out.println(blog);
        }
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了。
    建议
    先在Mysql中写出完整的SQL,再对应的去修改成我们的动态SQL实现通用即可!

  • 相关阅读:
    缓存穿透、击穿、雪崩
    阿里云安装Redis
    数据结构——单调栈
    排序算法:归并排序(递归和非递归)
    29 drf-Vue个人向总结-2
    笙默考试管理系统-MyExamTest----codemirror(35)
    Node 调试利器,前端、Node 开发必备 - VSCode JS Debug Terminal
    JAVA计算机毕业设计大学生兼职招聘网站计算机(附源码、数据库)
    舒服,给Spring贡献一波源码。
    H3C V7版本交换机配置IRF
  • 原文地址:https://blog.csdn.net/zhao854116434/article/details/126047886