什么是动态SQL

个人理解:动态SQL就是根据用户输入的参数不同,从而生成不同的SQL语句。
在Mybatis中,动态SQL就是在select,insert等标签中嵌入了if,set,foreach等标签。

搭建环境

本文接下来所举的例子,都是基于Blog(博客类)来说明的:

首先创建一个博客类(省略了getter和setter方法)

public class Blog {
    private String id;
    private String title;
    private String author;
    private Date create_time;
    private int views;
 }

相关接口

public interface BlogMapper {
    //插入博客
    int addBlog(Blog blog);

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

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

    //更新博客
    int updateBlog(Map map);

    //查询Id为1-3号的博客
    List<Blog> queryBlogForeach(Map map);
}

IF标签

<select id="queryBlogsIF" 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标签里嵌入if标签,if标签中的test属性用来判断数据库中的字段不为空,不为空则追加if标签里的SQL语句(有多个if时,记得在SQL语句开头加上and)

Choose(when otherwise)标签

这里跟Java语句中的switch case语句道理类似:

<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>

choose标签只会选择其中一条when标签中的语句执行,即满足test的第一个。

Set标签

当执行更新操作的动态SQL时,会用到set标签:

<update id="updateBlog" parameterType="map">
        update blog
        <set>
            <!--if标签中的SQL语句中别忘记加逗号,最后一个if标签中可以不加逗号-->
            <if test="title != null">
                title = #{title},
            </if>
            <if test="author != null">
                author = #{author}
            </if>
        </set>
        where id = #{id}
</update>

【注】在if标签中的SQL语句别忘记加逗号(最后一个If标签的逗号可加可不加,Mybatis可以去掉多余的逗号)

Foreach标签

动态SQL的另外一个常用操作需求就是针对集合进行遍历,通常是构建IN条件语句的时候

<!--
        select * from blog where 1=1 and (id=1 or id=2 or id=3)
        我们传递一个万能的Map,里面可以存放一个Collection集合
        其中open属性代表拼接的sql语句以什么开始,close则代表以什么结束
        separator代表分隔符
-->
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
    select * from blog
     <where>
        <foreach collection="ids" item="id" open="(" separator="or" close=")">
           id = #{id}
        </foreach>
     </where>
 </select>

这个collection属性值为存放在map里面的集合的键名(Key)
item属性值表示从这个集合中遍历的每一项都取名为id
其中open属性代表拼接的sql语句以什么开始
close则代表以什么结束
separator代表分隔符


测试代码

@Test
    public void test5(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Map map = new HashMap();
        String[] ids = {"1","2","3"};
        //这里的map的键为ids
        map.put("ids",ids);
        List<Blog> blogs = mapper.queryBlogForeach(map);
        for(Blog blog:blogs){
            System.out.println(blog);
        }
        sqlSession.close();
    }

Trim标签

它是一款自定义标签,具体功能如下:

<select id="" >
 select * from blog
 
  <trim prefix="WHERE" prefixoverride="AND |OR">

   <if test="name != null and name.length()>0"> AND name=#{name}</if>

   <if test="author != null and author.length()>0"> AND author=#{author}</if>

  </trim>
</select>

这里,prefix代表要定制的SQL语句的前缀是什么
prefixoverride="AND |OR"代表从前往后数,去掉第一个 AND 或 OR

update blog

  <trim prefix="set" suffixoverride="," suffix=" where id = #{id} ">

    <if test="name != null and name.length()>0"> name=#{name} , </if>

    <if test="author != null and author.length()>0"> author=#{author} ,  </if>

  </trim>

suffix代表定制的SQL语句后缀
suffixoverride = “,” 代表从后往前数,去掉第一个(也就是从前往后数的最后一个)逗号