MyBatis动态sql常用标签

一、简介

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。

二、常用标签

图片转载
MyBatis动态sql常用标签

if标签

if 标签通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。这条语句提供了一个可选的文本查找类型的功能。

<select id="findNameBySid" parameterType="int" resultMap="stafflist">
        SELECT * FROM staff                
        <if test="sid!=null">
        	sid=#{sid}
        </if>
         <if test="urealname!=null">
         	AND urealname LIKE concat(concat('%',#{urealname}),'%')
         </if>
    </select>

tirm、where、set

  • 之前在if语句时,为了让SQL语句的拼接不报错,我们在所有的if语句中的SQL语句前加上了and ,并在where后面添加了1=1,作为补充条件,不够灵活。现在我们可以使用where标签解决这个问题,
  • where标签拼接的SQL语句,如果是以and或or开头的,比如只有后一条判断满足时,where后直接跟上and,where标签可以自动的将这个and或or字段去除。
  • 同样的,自定义tirm标签也拥有这种功能,并且应用面更加的广泛
    tirm标签拥有四个子属性:prefix ,prefixOverrides ,suffix ,suffixOverrides。
    MyBatis动态sql常用标签
 		<select id="findNameBySid" parameterType="int" resultMap="stafflist">
        SELECT * FROM staff
        <where>
            <trim suffix="" suffixOverrides="and">
                <if test="sid!=null">
                    sid=#{sid}
                </if>
                <if test="urealname!=null">
                    AND urealname LIKE concat(concat('%',#{urealname}),'%')
                </if>
            </trim>
        </where>
    </select>

类似的还有用于update修改数据语句中的set标签,
set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。

	<update id="update" parameterType="Staff">
        UPDATE staff
        <trim suffix="where uid=#{uid}" suffixOverrides=",">
            <set>
                <if test="uid!=null">uid=#{uid},</if>
                <if test="pid!=null">pid=#{pid},</if>
                <if test="sid!=null">sid=#{sid},</if>
                <if test="uname!=null">uname=#{uname},</if>
                <if test="upsw!=null">upsw=#{upsw},</if>
                <if test="urealname!=null">urealname=#{urealname},</if>
            </set>
        </trim>
    </update>

choose, when, otherwise

有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<select id="findStaffByChoose" resultType="Staff">
        SELECT * FROM staff WHERE 1=1
        <choose>
            <when test="urealname!=null">
                AND urealname LIKE concat(concat('%',#{urealname}),'%')
            </when>
            <when test="upsw!=666">
                AND upsw=#{upsw}
            </when>
            <otherwise>
                AND uname=#{uname}
            </otherwise>
        </choose>
    </select>

foreach

foreach类似于Java中的for循环,我们可以对传入的数组,集合等数据集进行循环遍历,通常用于构建in条件语句

foreach的属性常用的有六个:collection ,item ,index , open ,close。

  • collection:要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用(“keyname”,keyname),以keyname作为键。

    • 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list 。
    • 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array 。
    • 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key。
  • item:集合中元素迭代时的别名,该参数为必选。

  • index:在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选

  • open:foreach代码的开始符号,一般是(,和close=")"合用。常用在in(),values()时。该参数可选

  • separator:元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。

  • close: foreach代码的关闭符号,一般是),和open="("合用。常用在in(),values()时。该参数可选。

以传入Map类型的数据为例:

<select id="findStaffByMap" resultType="Staff">
        SELECT * FROM staff WHERE urealname LIKE concat(concat('%',#{urealname}),'%') AND upsw IN
        <foreach collection="list" item="map" open="(" separator="," close= ")">
            #{map}
        </foreach>
    </select>
private static void test3() {
        SqlSession session = MybatisUtil.getSession();
        Map<String, Object> map = new HashMap<String, Object>();
        List list = new ArrayList();
        list.add(123);
        list.add(666);
        map.put("urealname","博");
        map.put("list",list);
        List<Staff> staffByMap = session.getMapper(StaffMapper.class).findStaffByMap(map);
        for (Staff staff : staffByMap) {
            System.out.println(staff.getUrealname()+"\t"+staff.getSid());
        }
    }
上一篇:关于sql group by使用的一些注意点


下一篇:XML映射中关于主键自增长的两种映射方法