1、什么是动态SQL

动态SQL是MyBatis的强大特性之一。如果你使用过JDBC或其它类似的框架,你应该能理解根据不同条件拼接SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。其实动态SQL就是根据不同的条件生成不同的SQL语句。
MyBatis动态SQL:https://mybatis.org/mybatis-3/zh/dynamic-sql.html

环境搭建

  1. DROP TABLE IF EXISTS `blog`;
  2. CREATE TABLE `blog` (
  3. `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '博客id',
  4. `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '博客标题',
  5. `author` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '博客作者',
  6. `create_time` datetime NOT NULL COMMENT '创建时间',
  7. `views` int(30) NOT NULL COMMENT '浏览量',
  8. PRIMARY KEY (`id`) USING BTREE
  9. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
  10. INSERT INTO `blog` VALUES ('1', 'MyBatis如此简单', '狂神说', '2021-03-06 21:12:22', 1);
  11. INSERT INTO `blog` VALUES ('2', 'Spring如此简单', '狂神说', '2021-03-06 21:13:27', 2);
  12. INSERT INTO `blog` VALUES ('3', 'Java如此简单', '狂神说', '2021-03-06 21:13:27', 3);
  13. INSERT INTO `blog` VALUES ('4', '微服务如此简单', '狂神说', '2021-07-15 10:23:56', 1000);

实体类

package domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Blog {
    private String id;
    private String title;
    private String author;
    private String createTime;
    private int views;
}

BlogMapper接口

package mapper;
import domain.Blog;
import java.util.List;
import java.util.Map;
public interface BlogMapper {
    public List<Blog> getBlog(Map<String,Object> map);//查询所有
    public void update(Map<String,Object> map);//更新
}

BlogMapper.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.BlogMapper">

    <select id="getBlog" resultType="domain.Blog" parameterType="map">
        select * from blog
    </select>
</mapper>

1.1、标签

<select id="getBlog" resultType="domain.Blog" parameterType="map">
        select * from blog where 1=1

        <if test="title!=null">
            and title=#{test}
        </if>

        <if test="author!=null">
            and author=#{author}
        </if>
    </select>

其实就是一个拼接SQL,如果title不为空,就把”and title=#{test}”拼接到select语句后面。

测试

public class junit {
    @Test
    public void one(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Map<String,Object> map=new HashMap<>();
        map.put("title","Java如此简单");
        List<Blog> blog = mapper.getBlog(map);
        for (Blog blog1 : blog) {
            System.out.println(blog1);
        }
        sqlSession.close();
    }
}

1.2、标签

为了简化上面where 1 = 1的条件拼装,我们可以采用标签来简化开发。

    <select id="getBlog" resultType="domain.Blog" parameterType="map">
        select * from blog
        <where>
            <if test="title!=null">
                and title=#{test}
            </if>
            <if test="author!=null">
                and author=#{author}
            </if>
        </where>
    </select>

1.3、标签

其实choose标签和Java里面的switch一样,自带一个break!

 <select id="getBlog" resultType="domain.Blog" parameterType="map">
        select * from blog
        <where>
            <choose>
                <when test="title!=null">
                    and title=#{title}
                </when>
                <when test="author!=null">
                    and author=#{author}
                </when>
                <otherwise>
                    and views=#{views}
                </otherwise>
            </choose>
        </where>
    </select>

1.4、标签

set会自动前置SET关键字,同时也会删掉无关的逗号

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

1.5、标签

有的时候,我们可能会将一些功能的部分抽取出来,方便使用,减少冗余。

 <sql id="one">
        <if test="title!=null">
            title=#{title},
        </if>
        <if test="author!=null">
            author=#{author},
        </if>
        <if test="views!=null">
            views=#{views},
        </if>
    </sql>
  • 在需要使用的地方使用标签引用即可
    <update id="update" parameterType="map">
          update blog
          <set>
              <include refid="one"></include>
          </set>
          where id=#{id}
      </update>
    

1.6、标签

标签里面的的四个属性:

  1. collection:里面存放的是一个集合
  2. item:遍历时的每一个元素
  3. open:起始位置的拼接符
  4. separator:隔断符
  5. close:结束位置的拼接符
<select id="getBlogForeach" resultType="domain.Blog" parameterType="map">
        select *from blog
        <where>
            <foreach collection="ids" item="id" open="and id in(" close=")" separator=",">
                #{id}
            </foreach>
        </where>
    </select>
  @Test
    public void one(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Map<String,Object> map=new HashMap<>();
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        map.put("ids",ids);
        List<Blog> blog = mapper.getBlogForeach(map);
        for (Blog blog1 : blog) {
            System.out.println(blog1);
        }
        sqlSession.close();
    }

2、总结

动态SQL的本质就是再拼接SQL,我们只要保证SQL的准确性,按照SQL的格式·,去排列组合就可以了。