动态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,再见!