动态 SQL 是 MyBatis 的强大特性之一。如果使用JDBC等框架,拼接SQL语句是一件很痛苦的事。现在使用MyBatis能够完成不同条件下不同的SQL拼接。
当我们在注册登录时,面临填写必要信息的情况,密码等字段是必填字段,生日等类似的字段是非必填字段。那在注册(添加)用户时,我们不确定用户填写的字段传入(可能会填也可能不会填),程序要如何编写呢?
这个时候需要动态标签来判断了 定义Mapper接口:
@Mapper
public interface UserInfoMapperXML {
Integer insertUser3(UserInfo userInfo);
}数据库中可以设置字段的默认值,如果未传入参数,那就会使用数据库中默认值 xml实现:
<insert id="insertUser3">
insert into user_info (
username,
`password`,
age,
<if test="gender !=null>//如果gender参数不为null,此处使用属性名称
gender,//拼接SQL字段,使用字段名
</if>
phone)
values(
#{username},
#{age},
<if test="gender !=null>//如果gender参数不为null,赋值
#{gender},//进行赋值
</if>
#{phone})
</insert>前面只是一个gender字段是选填项,如果有多个字段是选填(提前设置好数据库字段的结构),我们要使用 标签结合标签,对多个字段采用动态生成的方法。 首先,介绍一下< trim>标签的属性(后面会用到): prefix: 为SQL语句添加前缀。 suffix: 为SQL语句添加后缀。 prefixOverrides: 去除SQL语句前面的关键字或字符。 suffixOverrides: 去除SQL语句后面的关键字或字符
现在有两个选填,我们运行测试一下:
<insert id="insertUser3">
insert into user_info (username,`password`,age,
<if test="gender!=null">
gender,
</if>
<if test="phone!=null">
phone
</if>
)
VALUES (#{username},#{password},#{age},
<if test="gender!=null">
#{gender},
</if>
<if test="phone!=null">
#{phone}
</if>
)
</insert>
当选填的两个选项都为空时,会发现报错,仔细观察。 报错原因是:逗号;三个选项填完后,age后面有一个逗号,但是按照上面的情况会发现age后面木有选项了,这个逗号应该怎么办呢?
或许有聪明的大佬会说:把逗号放在属性的前面,就可以正常运行了

但是如果不止两个选填,字段全是选填 该如何放置呢? 按照大佬的思路,继续放到字段前面:


显然,这个办法在多个选填面前失效了。此时就需要拿出前面给出的标签属性了。
<insert id="insertUser3">
insert into user_info (
<trim prefixOverrides=",">
<if test="username!=null">
username
</if>
<if test="password!=null">
,password
</if>
<if test="age!=null">
,age
</if>
<if test="gender!=null">
,gender
</if>
<if test="phone!=null">
,phone
</if>
</trim>
)
VALUES (
<trim prefixOverrides=",">
<if test="username!=null">
#{username}
</if>
<if test="password!=null">
,#{password}
</if>
<if test="age!=null">
,#{age}
</if>
<if test="gender!=null">
,#{gender}
</if>
<if test="phone!=null">
,#{phone}
</if>
</trim>
)
</insert>
我们在数据库中查询时,肯定要有查询条件,多个条件之间要用and连接。
定义Mapper接口:
List<UserInfo> selectByCondition(UserInfo userInfo);xml实现:从user表中查以phone和deleteFlag为条件的数据
<select id="selectByCondition" resultType="com.zc.mybatis.model.UserInfo">
select *from user_info
where phone=#{phone} and delete_flag=#{deleteFlag}
</select> 但是在各大购物平台,都有商品筛选功能,他的实现就是动态组装where条件

仿照前面标签的做法,选择多个选项时,使用prefixOverrides去除前缀(否则会出现SQL语句错误的情况哦)
<select id="selectByCondition" resultType="com.zc.mybatis.model.UserInfo">
select *from user_info
<trim prefixOverrides="and">
<if test="phone!=null">
and phone=#{phone}
</if>
<if test="deleteFlag!=null">
and delete_flag=#{deleteFlag}
</if>
</trim>
</select>当然,你也可以使用where标签: 当where语句为空时,会去除where关键字 当where语句块有查询条件时,会添加where关键字,也会去除前缀and关键字,使用更加便利。
<select id="selectByCondition" resultType="com.zc.mybatis.model.UserInfo">
select *from user_info
<where>
<if test="phone!=null">
and phone=#{phone}
</if>
<if test="deleteFlag!=null">
and delete_flag=#{deleteFlag}
</if>
</where>
</select>
根据传入用户对象属性来更新用户数据,可以使用标签指定动态内容 xml实现:
<update id="updateByCondition">
update user_info
<set>
<if test="password!=null">
password=#{password},
</if>
<if test="age!=null">
age=#{age},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id=#{id}//更新条件
</update>
注意:set标签:动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.当然,你也可以根据< trim>标签替换
对集合进行遍历使用该标签,属性如下: collection:绑定⽅法参数中的集合,如List,Set,Map或数组对象 item:遍历的每一个对象 open:语句开头的字符串 close:语句结束的字符串 separator:每次遍历之间间隔的字符串
mapper接口:
Integer batchDelete(List<Integer> ids);xml实现:根据多个id,删除用户数据
<delete id="batchDelete">
delete from user_info where id in
//collection="ids":元素集合
//item="id":元素变量名
//separator=",":元素分隔符
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
在xml映射⽂件中配置的SQL,有时可能会存在很多重复的⽚段,此时就会存在很多冗余的代码

我们通过对这些代码进行抽取,将其封装到一个SQL片段,然后再通过< include> 标签引用
//<sql>定义可重用的sql片段
<sql id="allColumn">
id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>通过< include>标签在原来抽取的地方进行引用即可
<select id="queryById" resultType="com.example.demo.model.UserInfo">
select
<include refid="allColumn"></include>
from userinfo where id= #{id}
</select>