• MyBatis友人帐之动态SQL


    一、简介

    1.1概述

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

    动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
    
      -------------------------------
      - if
      - choose (when, otherwise)
      - trim (where, set)
      - foreach
      -------------------------------

     1.2环境搭建

    数据库环境

    1. CREATE TABLE `blog` (
    2. `id` varchar(50) NOT NULL COMMENT '博客id',
    3. `title` varchar(100) NOT NULL COMMENT '博客标题',
    4. `author` varchar(30) NOT NULL COMMENT '博客作者',
    5. `create_time` datetime NOT NULL COMMENT '创建时间',
    6. `views` int(30) NOT NULL COMMENT '浏览量'
    7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    这个表使用InnoDB作为存储引擎,并且指定了字符集为utf8。每个字段后面的注释用于说明其含义。例如,id字段后面的注释是博客id

    编写实体类

    1. package com.yanyu.bojo;
    2. import lombok.Data;
    3. import java.util.Date;
    4. @Data
    5. public class Blog {
    6. private String id;
    7. private String title;
    8. private String author;
    9. private Date createTime;
    10. private int views;
    11. //set,get....
    12. }

     编写Mapper接口及xml文件

    1. "1.0" encoding="UTF-8" ?>
    2. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    4. "com.yanyu.dao.BlogMapper">
    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.yanyu.dao.BlogMapper">
    6. mapper>

    IDutil工具类

    1. package com.yanyu.utils;
    2. import org.junit.Test;
    3. import java.util.UUID;
    4. public class IDUtil {
    5. public static String genId(){
    6. return UUID.randomUUID().toString().replaceAll("-","");
    7. }
    8. @Test
    9. public void test(){
    10. System.out.println(IDUtil.genId());
    11. System.out.println(IDUtil.genId());
    12. System.out.println(IDUtil.genId());
    13. System.out.println(IDUtil.genId());
    14. }
    15. }

    这段代码是用Java语言编写的,用于定义一个名为genId的静态方法。这个方法的作用是生成一个随机的字符串,作为一个唯一的标识符。这个方法的具体步骤如下:

    • 调用UUID.randomUUID()方法,生成一个随机的通用唯一标识符(UUID),它是一个由32个十六进制数字组成的字符串,中间有四个连字符分隔。例如,3f06af63-a93c-11d3-bbe8-1a2124a50b11是一个UUID。
    • 调用toString()方法,将UUID转换为一个普通的字符串。
    • 调用replaceAll("-","")方法,将字符串中的所有连字符替换为空字符串,即删除掉连字符。这样,就得到了一个由32个十六进制数字组成的字符串,没有任何分隔符。例如,3f06af63a93c11d3bbe81a2124a50b11是一个去掉连字符的UUID。

    插入初始数据

    编写接口

    1. //新增一个博客
    2. int addBlog(Blog blog);

    sql配置文件

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

    测试

    1. import com.yanyu.dao.BlogMapper;
    2. import com.yanyu.pojo.Blog;
    3. import com.yanyu.utils.IDUtil;
    4. import com.yanyu.utils.MybatisUtils;
    5. import org.apache.ibatis.session.SqlSession;
    6. import org.junit.Test;
    7. import java.util.Date;
    8. public class Mytest {
    9. @Test
    10. public void addInitBlog(){
    11. SqlSession session = MybatisUtils.getSession();
    12. BlogMapper mapper = session.getMapper(BlogMapper.class);
    13. Blog blog = new Blog();
    14. blog.setId(IDUtil.genId());
    15. blog.setTitle("Mybatis如此简单");
    16. blog.setAuthor("狂神说");
    17. blog.setCreateTime(new Date());
    18. blog.setViews(9999);
    19. mapper.addBlog(blog);
    20. blog.setId(IDUtil.genId());
    21. blog.setTitle("Java如此简单");
    22. mapper.addBlog(blog);
    23. blog.setId(IDUtil.genId());
    24. blog.setTitle("Spring如此简单");
    25. mapper.addBlog(blog);
    26. blog.setId(IDUtil.genId());
    27. blog.setTitle("微服务如此简单");
    28. mapper.addBlog(blog);
    29. session.close();
    30. }
    31. }

     二、动态SQL详解

    2.1if 语句

    需求:根据作者名字和博客名字来查询博客!如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询

    编写接口类

    1. //需求1
    2. List queryBlogIf(Map map);

    编写SQL语句

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

    测试

    1. @Test
    2. public void testQueryBlogIf(){
    3. SqlSession session = MybatisUtils.getSession();
    4. BlogMapper mapper = session.getMapper(BlogMapper.class);
    5. HashMap map = new HashMap();
    6. map.put("title","Mybatis如此简单");
    7. map.put("author","狂神说");
    8. List blogs = mapper.queryBlogIf(map);
    9. System.out.println(blogs);
    10. session.close();
    11. }

    这样写我们可以看到,如果 author 等于 null,那么查询语句为 select * from user where title=#{title},但是如果title为空呢?那么查询语句为 select * from user where and author=#{author},这是错误的 SQL 语句,如何解决呢?请看下面的 where 语句!

    2.2Where语句

    修改上面的SQL语句

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

    where语句的优点是它会自动在输出的地方插入一个WHERE关键字,并且去除掉多余的AND或OR12。这样就可以避免SQL语法错误或者无效的查询。

    2.3Set语句

    同理,上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词,我们怎么处理呢?

    编写接口方法

    int updateBlog(Map map);

     sql配置文件

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

    测试语句

    1. @Test
    2. public void testUpdateBlog(){
    3. SqlSession session = MybatisUtils.getSession();
    4. BlogMapper mapper = session.getMapper(BlogMapper.class);
    5. HashMap map = new HashMap();
    6. map.put("title","动态SQL");
    7. map.put("author","秦疆");
    8. map.put("id","9d6a763f5e1347cebda43e2a32687a77");
    9. mapper.updateBlog(map);
    10. session.close();
    11. }

    set语句的优点是它会自动在输出的地方插入一个SET关键字,并且去除掉多余的逗号12。这样就可以避免SQL语法错误或者无效的更新。

    2.4choose语句

    有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

    编写接口方法

    List queryBlogChoose(Map map);

     sql配置文件

    1. <select id="queryBlogChoose" parameterType="map" resultType="blog">
    2. select * from blog
    3. <where>
    4. <choose>
    5. <when test="title != null">
    6. title = #{title}
    7. when>
    8. <when test="author != null">
    9. and author = #{author}
    10. when>
    11. <otherwise>
    12. and views = #{views}
    13. otherwise>
    14. choose>
    15. where>
    16. select>

    测试类

    1. @Test
    2. public void testQueryBlogChoose(){
    3. SqlSession session = MybatisUtils.getSession();
    4. BlogMapper mapper = session.getMapper(BlogMapper.class);
    5. HashMap map = new HashMap();
    6. map.put("title","Java如此简单");
    7. map.put("author","狂神说");
    8. map.put("views",9999);
    9. List blogs = mapper.queryBlogChoose(map);
    10. System.out.println(blogs);
    11. session.close();
    12. }

    2.5trim语句

    MyBatis的trim语句是一种动态SQL的功能,它可以用于在SQL语句中去除不必要的空格、逗号、关键字等,或者给SQL语句添加一些前缀或后缀,以简化SQL语句的书写和提高执行效率。trim语句的用法是在