zoukankan      html  css  js  c++  java
  • Mybatis-动态SQL

    动态SQL

    什么是动态SQL: 根据不同的条件生成不同的SQL语句

    1. 搭建环境

    1. 准备数据库

    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;
    

    2. 创建一个基础工程

    1. 导包

    2. 编写配置文件

    3. 编写实体类

      package com.wang.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      import java.util.Date;
      
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class Blog {
          private int id;
          private String title;
          private String author;
          //日期用util包中的
          private Date createTime;
          private int views;
      }
      
    4. 编写实体类对应Mapper接口和对应的xml文件

    5. 插入数据

      1. 创建一个工具类,利用UUID作为数据库的id

        package com.wang.utils;
        
        import java.util.UUID;
        
        public class IdUtils {
        
            public static String getId() {
                return UUID.randomUUID().toString().replaceAll("-", "");
            }
        
        }
        
      2. 编写插入数据的接口及对应的mapper

        package com.wang.dao;
        
        import com.wang.pojo.Blog;
        
        public interface BlogMapper {
        
            //插入数据
            int addBlog(Blog blog);
        }
        
        <?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.wang.dao.BlogMapper">
        
            <insert id="addBlog" parameterType="Blog">
                insert into blog(id, title, author, create_time, views)
                values (#{id}, #{title}, #{author}, #{createTime}, #{views});
            </insert>
        
        </mapper>
        
      3. 插入数据

        package com.wang.dao;
        
        import com.wang.pojo.Blog;
        import com.wang.utils.IdUtils;
        import com.wang.utils.MybatisUtils;
        import org.apache.ibatis.session.SqlSession;
        import org.junit.Test;
        
        import java.util.Date;
        
        public class MyTest {
        
            @Test
            public void TestAddBlog() {
                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(9999);
        
                mapper.addBlog(blog);
        
                blog.setId(IdUtils.getId());
                blog.setTitle("Java");
                mapper.addBlog(blog);
        
                blog.setId(IdUtils.getId());
                blog.setTitle("Spring");
                mapper.addBlog(blog);
        
                blog.setId(IdUtils.getId());
                blog.setTitle("微服务");
                mapper.addBlog(blog);
        
                //增删改查要开启事务
                sqlSession.commit();
        
                sqlSession.close();
            }
        
        }
        

    2. IF

    1. 编写接口

    //查询博客
    List<Blog> queryBlogIF(Map map);
    

    2. 编写mapper文件

    <select id="queryBlogIF" 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>
    

    3. 测试

    @Test
    public void TestQueryBlogIF() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
    
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("author", "狂神说");
        List<Blog> blogs = mapper.queryBlogIF(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
    
        sqlSession.close();
    }
    

    3. choose(when, otherwise)

    类似Java中的switch语句, when相当于case, otherwise相当于default

    <select id="queryBlogChoose" 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>
    

    4. tirm(where, set)

    1. where

    由于使用where语句,如果第一个if不使用,则会在where后直接跟and,从而导致SQL语句报错

    在之前的if标签中,使用了where 1 = 1来避免这种情况,但是这样写时不正规的

    因此我们下面使用where标签来解决此问题

    <select id="queryBlogIF" 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>
    

    where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。**

    2. set

    使用set标签解决update只更新部分字段导致出现无关的逗号导致SQL报错

    <update id="updateBlog" parameterType="map">
        update blog
        <set>
            <if test="title != null">
                title = #{title},
            </if>
            <if test="author != null">
                author = #{author}
            </if>
        </set>
        where id = #{id}
    </update>
    

    3. trim

    如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能

    1. 与where等价的trim

    <trim prefix="WHERE" prefixOverrides="AND |OR ">
      ...
    </trim>
    

    2. 与set等价的trim

    <trim prefix="SET" suffixOverrides=",">
      ...
    </trim>
    

    5. Foreach

        <!--我们现在传递一个万能的map, 这个map中可以存在一个集合
            foreach中的collection标签为遍历的集合,item为集合中的元素
            open为每一个遍历元素的对应语句的头开头,close为结尾
            separator为其分隔符
        -->
        <select id="queryBlogForeach" parameterType="map" resultType="Blog">
            select * from blog
            <where>
                <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                    id = #{id}
                </foreach>
            </where>
        </select>
    
    @Test
    public void TestQueryBlogForeach() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
    
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        ArrayList<Integer> ids = new ArrayList<>();
        for (int i = 1; i < 4; i++) {
            ids.add(i);
        }
        map.put("ids", ids);
        List<Blog> blogs = mapper.queryBlogForeach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
    
        sqlSession.close();
    }
    

    6. SQL片段

    有的时候,我们会将一些公共的部分抽取出来,方便复用

    1. 使用sql标签抽取公共的部分

    <sql id="if-title-author">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    

    2. 在需要使用的地方使用include标签引用即可

    <select id="queryBlogIF" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <include refid="if-title-author">
            </include>
        </where>
    </select>
    

    3. 注意事项

    • 最好基于单表来定义SQL片段
    • 不要存在where标签

    7. 动态SQL的本质

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

    8. 总结

    • 动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
    • 建议:
      • 先在MySQL中写出完整的SQL语句
      • 再对应的去修改成为我们的动态SQL实现通用即可
  • 相关阅读:
    通过docker构建zabbix监控系统
    python中执行shell命令
    silverlight计时器的使用
    Silverlight学习笔记2:Silverlight中使用多线程实现倒计时
    silverlight全屏模式
    ASP.NET后台调用JavaScript
    JavaScript容易误解的概念
    Silverlight学习笔记1:创建一个Silverlight应用程序
    JavaScript中==和===的区别
    利用Visual Studio International Pack 实现对汉字的简单操作
  • 原文地址:https://www.cnblogs.com/wang-sky/p/13597103.html
Copyright © 2011-2022 走看看