Mybatis--动态SQL

发布于:2025-04-07 ⋅ 阅读:(21) ⋅ 点赞:(0)

动态SQL是MyBatis的重要特征之一,能够完成不同条件下的SQL拼接,参考文档:动态 SQL_MyBatis中文网

一、<if>标签

该标签主要适用的情况为实现必填字段和非必填字段:

例如下面的例子就是将用户表中的性别设置成了非必填字段:(XML实现)

 <insert id="insertUserByCondition">
        insert into user_info(username,password,age,
                              <if test="gender!=null">
                                  gender,
                              </if>
                              phone)
        VALUES (
                #{username},
                #{password},
                #{age},
        <if test="gender!=null">
            #{gender},
        </if>
            #{phone}
        )
    </insert>

这样即使不输入性别也可以添加成功。

二、<trim>标签

<if>标签虽好,但是存在一个问题,就是如果最后一个属性设置为了非必填属性,而且没有参数输入的话,这样最后传入参数的属性后面会有一个“,” 这会导致idea错误将其认为是其属性名的一部分,从而导致错误,而使用<trim>标签就可以解决这个问题。

首先<trim>标签有几个参数需要了解一下:

prefix:表示整个语句块以prefix的值作为前缀。

suffix:表示整个语句块以suffix的值作为后缀。

prefixOverrides:表示整个语句块要去除掉的前缀。

suffixOverrides:表示整个语句块要去除掉的后缀。

对一修改后的代码(将除phone属性外的属性都设置为了非必填属性):

 <insert id="insertUserByCondition">
        insert into user_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                password,
            </if>
            <if test="age!=null">
                age,
            </if>
            <if test="gender!=null">
                gender,
            </if>
                phone
        </trim>
        VALUES <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username!=null">
            #{username},
        </if>
        <if test="password!=null">
            #{password},
        </if>
        <if test="age!=null">
            #{age},
        </if>
        <if test="gender!=null">
            #{gender},
        </if>
        phone
    </trim>
    </insert>

三、<where>标签

<where>标签和<trim>标签较为类似,<where>标签主要解决动态查询时,会有一些多余的“and”或“or”,这点使用<trim>标签也可以实现,但是如果当所有的查询条件都为空时,<trim>标签仍会保留where语句,而<where>标签则不会。

下面是一个例子:

 <select id="queryByCondition" resultType="com.example.mybatisxml.Model.UserInfo">
        select id,username,password,age,gender,phone,delete_flag,create_time,update_time from user_info
        <where>
            <if test="age!=null">
                age = #{age}
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
            <if test="deleteFlag!=null">
                and delete_flag = #{deleteFlag}
            </if>
        </where>
    </select>

这样即使我什么都不输入,SQL语句仍然可以执行。

 @Test
    void queryByCondition() {
        List<UserInfo> list = userInfoXMLMapper.queryByCondition();
        System.out.println(list);
    }

四、<set>标签

相当于<trim prefix="set"  suffixOverrides=","> ,<set>就是可以动态插入set关键字,同时删除多余的“,”。

例如:

  <update id="updateUserByCondition">
        update user_info
        <set>
            <if test="username!=null">
                username = #{username},
            </if>
            <if test="age!=null">
                age = #{age},
            </if>
            <if test="age!=null">
                delete_flag = #{deleteFlag},
            </if>
        </set>
        where id = #{id}
    </update>

五、<foreach>标签

对集合遍历时可以使用该标签,该标签有如下属性:

collection:绑定方法参数中的集合,如List,Set,Map或者数组对象。

item:遍历时的每一个对象。

open:语句块开头的字符串。

close:语句块结束时的字符串。

separator:每次遍历之间间隔的字符串。

例如:

定义一个List集合,利用foreach遍历List集合,按照List中每个id来删除对应id的记录。

 <delete id="deleteUserByIds">
        delete from user_info
        where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

测试方法:

@Test
    void deleteUserByIds() {
        Integer[] tmp = new Integer[]{9,8,7,6,5,4,3,2};
        List<Integer> ids = Arrays.asList(tmp);
        System.out.println(userInfoXMLMapper.deleteUserByIds(ids));
    }

这样id为9,8,7,6,5,4,3,2的记录都被删除了。

六、<include>标签

由于在XML映射文件中配置的SQL会有很多的重复片段,我们就可以对重复的代码进行提取,将其通过<sql>标签封装到一个SQL片段,然后通过<include>标签再进行引用。

<sql>:定义可重用的SQL片段。

<include>:通过属性refid,指定包含的SQL片段。

例如:将用户表中所有属性封装到<sql>中,这样再次查询时就方便了很多,不过要注意给<sql>封装的代码块起一个名字。

<sql id="allColumn">
        id,username,password,age,gender,phone,delete_flag,create_time,update_time
    </sql>
    <select id="queryAllUser2" resultType="com.example.mybatisxml.Model.UserInfo">
        select 
            <include refid="allColumn"></include>
            from user_info
    </select>

ok,再见!