加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Mybatis-动态SQL

发布时间:2020-12-14 18:04:38 所属栏目:大数据 来源:网络整理
导读:动态SQL 目录 动态SQL 1. 搭建环境 1. 准备数据库 2. 创建一个基础工程 2. IF 1. 编写接口 2. 编写mapper文件 3. 测试 3. choose(when,otherwise) 4. tirm(where,set) 1. where 2. set 3. trim 1. 与where等价的trim 2. 与set等价的trim 5. Foreach 6. SQL片

动态SQL

目录
  • 动态SQL
    • 1. 搭建环境
      • 1. 准备数据库
      • 2. 创建一个基础工程
    • 2. IF
      • 1. 编写接口
      • 2. 编写mapper文件
      • 3. 测试
    • 3. choose(when,otherwise)
    • 4. tirm(where,set)
      • 1. where
      • 2. set
      • 3. trim
        • 1. 与where等价的trim
        • 2. 与set等价的trim
    • 5. Foreach
    • 6. SQL片段
      • 1. 使用sql标签抽取公共的部分
      • 2. 在需要使用的地方使用include标签引用即可
      • 3. 注意事项
    • 7. 动态SQL的本质
    • 8. 总结

什么是动态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实现通用即可

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读