动态 SQL 是 MyBatis 的强大特性之一。动态 SQL 可以根据运行时提供的条件,包括 参数值、逻辑判断、循环 等,动态生成SQL语句的各个部分的具体内容。
对动态SQL的学习主要是学习几个重要的标签,下面我们详细介绍:
例:根据可选参数插入用户信息
<insert id="insert2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into userinfo(username, password
<if test="photo != null">
,photo
</if>
) values (
#{username},
#{password}
<if test="photo != null">
,#{photo}
</if>
)
</insert>
注: test 中的 字段名,是传入对象中的 属性
,不是数据库字段。
虽然上面的
标签可以实现一些动态 SQL,但是如果所有的参数都是可选参数的情况下,只使用
标签就可能会出错。例如:
<insert id="insert2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into userinfo(
<if test="username != null">
username
</if>
<if test="password != null">
,password
</if>
) values (
<if test="username != null">
#{username}
</if>
<if test="password != null">
,#{password}
</if>
)
</insert>
上述这种情况下,如果只传入 username 参数,那么最终拼接的 SQL 语句为:insert into userinfo(,password)……显然,这是一个错误的 SQL 语句。
此时我们可以使用
标签结合
标签,解决上述问题:
trim 标签中的重要属性:
prefix
:表示整个语句块,以prefix的值作为前缀。suffix
:表示整个语句块,以suffix的值作为后缀。prefixOverrides
:表示整个语句块要去除掉的前缀。suffixOverrides
:表示整个语句块要去除掉的后缀。
使用
<insert id="insert2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into userinfo
<trim prefix="(" suffix=")" prefixOverrides=",">
<if test="username != null">
username
</if>
<if test="password != null">
,password
</if>
</trim>
values
<trim prefix="(" suffix=")" prefixOverrides=",">
<if test="username != null">
#{username}
</if>
<if test="password != null">
,#{password}
</if>
</trim>
</insert>
标签内部的条件会根据实际情况自动生成 where 子句。
标签会自动去除最前面的“
and
”和“or
”关键字。- 根据以上特性,
标签也可以使用 或 替换。
例:根据可选参数查询用户信息
<select id="getUserInfoByWhere" resultType="com.example.demo.model.UserInfo">
select * from userinfo
<where>
<if test="id > 0">
id=#{id}
</if>
<if test="photo != null">
and photo=#{photo}
</if>
</where>
</select>
标签内部的条件会根据实际情况自动生成 set 子句。
标签会自动去除最后面的
,
。- 根据以上特性,
标签也可以使⽤ 替换
例:设置可选参数更新用户信息
<update id="updateBySet">
update userinfo
<set>
password=#{password},
<if test="username != null">
username=#{username},
</if>
<if test="photo != null">
photo=#{photo}
</if>
</set>
where id=#{id}
</update>
下面是
collection
:绑定方法参数中的集合,如 List,Set,Map或数组对象.item
:遍历时的每⼀个对象.open
:语句块开头的字符串.close
:语句块结束的字符串.separator
:每次遍历之间间隔的字符串.
例如根据用户 id 批量删除用户信息:
接口:
int deleteByIds(List<Integer> ids);
xml 实现:
<delete id="deleteByIds">
delete from userinfo
where id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</delete>