Mybatis工作中常用动态SQL总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Weixiaohuai/article/details/89258377

一、简介

上篇文章,我们介绍了Mybatis常用的关系映射,本文将在上篇文章项目的基础上,总计一下Mybatis中动态SQL的常用用法,项目结构可以从这里https://gitee.com/weixiaohuai/springboot-mybatis.git下载。相信大家没用Mybatis之前,都碰到过各种条件判断拼接SQL、需要去掉多余的逗号等痛苦,Mybatis中的动态SQL能很好的解决上面说的情况,可以很灵活的组装SQL语句,从而提高开发效率。

二、动态SQL

Mybatis动态SQL提高了很多标签,如if、choose、where 、set、trim、foreach、sql等,下面我们逐个讲解每一个标签的用法:

【a】if标签

判断语句,通常用于满足某个条件就拼接上某种过滤条件等场景。

(1) mapper接口:

/**
     * if
     */
    List<Map<String, Object>> testIf(@Param("sid") Integer sid, @Param("sname") String sname);

(2) mapper映射文件:

<!--if-->
    <select id="testIf" resultType="java.util.Map">
        select *
        from tbl_student t
        where 1 = 1
        <if test="sid != null and sid != ''">
            and t.s_id = #{sid}
        </if>
        <if test="sname != null and sname != ''">
            and t.s_name = #{sname}
        </if>
    </select>

(3) 测试用例:

@Test
    public void testIf() {
        List<Map<String, Object>> list1 = studentMapper.testIf(null, "学生5");
        for (Map<String, Object> map : list1) {
            System.out.println(map);
        }

        List<Map<String, Object>> list2 = studentMapper.testIf(1, "");
        for (Map<String, Object> map : list2) {
            System.out.println(map);
        }

        List<Map<String, Object>> list3 = studentMapper.testIf(2, "学生2");
        for (Map<String, Object> map : list3) {
            System.out.println(map);
        }
    }

(4) 测试结果:

【b】choose标签

功能类似if,其中包含when/otherwise子标签。

(1) mapper接口:

 /**
     * choose
     */
    List<Map<String, Object>> testChoose(@Param("sid") Integer sid, @Param("sname") String sname);

(2) mapper映射文件:

 <!--choose(when/otherwise)-->
    <select id="testChoose" resultType="java.util.Map">
        select *
        from tbl_student t
        where 1 = 1
        <choose>
            <when test="sid != null and sid != ''">
                and t.s_id = #{sid}
            </when>
            <when test="sname != null and sname != ''">
                and t.s_name = #{sname}
            </when>
            <otherwise>
                and t.s_id in (1,2)
            </otherwise>
        </choose>
    </select>

(3) 测试用例:

@Test
    public void testChoose() {
        List<Map<String, Object>> list1 = studentMapper.testChoose(null, "学生5");
        for (Map<String, Object> map : list1) {
            System.out.println(map);
        }

        List<Map<String, Object>> list2 = studentMapper.testChoose(1, "");
        for (Map<String, Object> map : list2) {
            System.out.println(map);
        }

        List<Map<String, Object>> list3 = studentMapper.testChoose(2, "学生2");
        for (Map<String, Object> map : list3) {
            System.out.println(map);
        }

        List<Map<String, Object>> list4 = studentMapper.testChoose(null, null);
        for (Map<String, Object> map : list4) {
            System.out.println(map);
        }
    }

(4) 测试结果:

【c】where标签

(1) mapper接口:

/**
     * where
     */
    List<Map<String, Object>> testWhere01(@Param("sid") Integer sid, @Param("sname") String sname);

    List<Map<String, Object>> testWhere02(@Param("sid") Integer sid, @Param("sname") String sname);

(2) mapper映射文件:

 <select id="testWhere01" resultType="map">
        /*假设只有第二个条件满足,此时sql: select * from tbl_student t where and t.s_name = 'xxx' 明显不正确
        此时,可以使用where标签来帮助我们去掉多余的and
        */
        select *
        from tbl_student t
        where
        <if test="sid != null and sid != ''">
            t.s_id = #{sid}
        </if>
        <if test="sname != null and sname != ''">
            and t.s_name = #{sname}
        </if>
    </select>

    <!--where-->
    <select id="testWhere02" resultType="map">
        select *
        from tbl_student t
        <where>
            <if test="sid != null and sid != ''">
                and t.s_id = #{sid}
            </if>
            <if test="sname != null and sname != ''">
                and t.s_name = #{sname}
            </if>
        </where>
    </select>

(3) 测试用例:

 @Test
    public void testWhere01() {
        List<Map<String, Object>> list1 = studentMapper.testWhere01(null, "学生5");
        for (Map<String, Object> map : list1) {
            System.out.println(map);
        }
    }

    @Test
    public void testWhere02() {
        List<Map<String, Object>> list1 = studentMapper.testWhere02(null, "学生5");
        for (Map<String, Object> map : list1) {
            System.out.println(map);
        }

        List<Map<String, Object>> list2 = studentMapper.testWhere02(1, "");
        for (Map<String, Object> map : list2) {
            System.out.println(map);
        }

        List<Map<String, Object>> list3 = studentMapper.testWhere02(2, "学生2");
        for (Map<String, Object> map : list3) {
            System.out.println(map);
        }

        List<Map<String, Object>> list4 = studentMapper.testWhere02(null, null);
        for (Map<String, Object> map : list4) {
            System.out.println(map);
        }
    }

(4) 测试结果:

【d】set标签

可以自动去除sql中的多余的逗号‘,’

(1) mapper接口:

 /**
     * set
     */
    Integer testSet(@Param("sid") Integer sid, @Param("sname") String sname);

(2) mapper映射文件:

 <!--set-->
    <!--
        set标签: 可以自动去除sql中的多余的逗号‘,’
    -->
    <update id="testSet">
        update tbl_student t
        /*此时执行的sql为: update tbl_student t SET s_name = ? WHERE s_id = ? */
        <set>
            <if test="sname != null and sname != ''">
                s_name = #{sname},
            </if>
        </set>
        <where>
            s_id = #{sid}
        </where>
    </update>

(3) 测试用例:

 @Test
    public void testSet() {
        studentMapper.testSet(1, "zhangsan");
        List<Map<String, Object>> list = studentMapper.testWhere01(1, null);
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }

(4) 测试结果:

【e】trim标签

trim标签: 一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀.
        prefix: 给sql语句拼接的前缀
        prefixOverrides: 去除sql语句前面的关键字或者字符,假设该属性指定为”AND”,当sql语句的开头为”AND”,trim标签将会去除该”AND”
        suffix: 给sql语句拼接的后缀
        suffixOverrides: 去除sql语句后面的关键字或者字符

(1) mapper接口:

 /**
     * 使用trim实现where同样功能
     */
    List<Map<String, Object>> testTrimWhere(@Param("sid") Integer sid, @Param("sname") String sname);

 /**
     * 使用trim实现set同样功能
     */
    Integer testSetTrim(@Param("sid") Integer sid, @Param("sname") String sname);

(2) mapper映射文件:

 <!--使用trim实现where等价的功能-->
    <select id="testTrimWhere" resultType="map">
        select *
        from tbl_student t
        /*
        trim标签: 一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀
        prefix: 给sql语句拼接的前缀
        prefixOverrides: 去除sql语句前面的关键字或者字符,假设该属性指定为”AND”,当sql语句的开头为”AND”,trim标签将会去除该”AND”
        suffix: 给sql语句拼接的后缀
        suffixOverrides: 去除sql语句后面的关键字或者字符
        */
        <trim prefix="where" prefixOverrides="and | or">
            <if test="sid != null and sid != ''">
                and t.s_id = #{sid}
            </if>
            <if test="sname != null and sname != ''">
                and t.s_name = #{sname}
            </if>
        </trim>
    </select>


 <!--使用trim实现set同样的功能-->
    <update id="testSetTrim">
        update tbl_student t
        <trim prefixOverrides="," prefix="set" suffixOverrides=",">
            <if test="sname != null and sname != ''">
                ,s_name = #{sname},
            </if>
        </trim>
        <where>
            s_id = #{sid}
        </where>
    </update>

(3) 测试用例:

 @Test
    public void testTrimWhere() {
        List<Map<String, Object>> list1 = studentMapper.testTrimWhere(null, "学生5");
        for (Map<String, Object> map : list1) {
            System.out.println(map);
        }

        List<Map<String, Object>> list2 = studentMapper.testTrimWhere(1, "");
        for (Map<String, Object> map : list2) {
            System.out.println(map);
        }

        List<Map<String, Object>> list3 = studentMapper.testTrimWhere(2, "学生2");
        for (Map<String, Object> map : list3) {
            System.out.println(map);
        }

        List<Map<String, Object>> list4 = studentMapper.testTrimWhere(null, null);
        for (Map<String, Object> map : list4) {
            System.out.println(map);
        }
    }

@Test
    public void testSetTrim() {
        studentMapper.testSetTrim(1, "zhangsan2");
        List<Map<String, Object>> list = studentMapper.testWhere01(1, null);
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }

(4) 测试结果:

【f】foreach标签

foreach标签:主要用在构建in条件中,迭代一个集合.

item: 表示集合中每一个元素进行迭代时的别名,

index: 指 定一个名字,用于表示在迭代过程中,每次迭代到的位置,

open: 表示该语句以什么开始,

separator: 表示在每次进行迭代之间以什么符号作为分隔符,

close: 表示以什么结束。

(1) mapper接口:

  /**
     * foreach
     */
    List<Map<String, Object>> testForEach(@Param("pkids") List<Integer> pkids);

(2) mapper映射文件:

 <!--foreach-->
    <select id="testForEach" resultType="map">
        select * from tbl_student t
        where 1 = 1
        and t.s_id in
        /*
        foreach标签:主要用在构建in条件中,迭代一个集合
        item: 表示集合中每一个元素进行迭代时的别名,
        index: 指 定一个名字,用于表示在迭代过程中,每次迭代到的位置,
        open: 表示该语句以什么开始,
        separator: 表示在每次进行迭代之间以什么符号作为分隔符,
        close: 表示以什么结束。
        */
        <foreach collection="pkids" open="(" close=")" separator="," index="index" item="pkid">
            #{pkid}
        </foreach>
    </select>

(3) 测试用例:

  @Test
    public void testForEach() {
        List<Map<String, Object>> list = studentMapper.testForEach(Arrays.asList(1, 2, 3, 4, 5));
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }

(4) 测试结果:

【g】 sql标签

sql片段:就是预先定义后的一些sql语句。等其他sql需要的时候直接拿来用

id : sql片段的唯一标识,在需要引用sql片段的时候使用 <include refid="student_column"/> 标签引入即可;

尽量使用单表的字段来定义sql片段,重用性高

(1) mapper接口:

   /**
     * sql
     */
    List<Map<String, Object>> testSql();

(2) mapper映射文件:

<!--sql-->
    <!--
        sql片段:就是预先定义后的一些sql语句。等其他sql需要的时候直接拿来用
        id : sql片段的唯一标识,在需要引用sql片段的时候使用 <include refid="student_column"/> 标签引入即可
        尽量使用单表的字段来定义sql片段,重用性高
    -->
    <sql id="student_column">
        s_id,
        s_name
    </sql>

    <select id="testSql" resultType="map">
        select
        <include refid="student_column"/>
        from tbl_student
    </select>

(3) 测试用例:

 @Test
    public void testSql() {
        List<Map<String, Object>> list = studentMapper.testSql();
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }

(4) 测试结果:

三、总结

以上就是关于Mybatis中动态SQL部分的一些认识和使用详解,本文只是笔者学习上的一些见解和总结,希望对大家的学习有所帮助。

猜你喜欢

转载自blog.csdn.net/Weixiaohuai/article/details/89258377