动态SQL
在 MyBatis 中,动态 SQL 是一种强大的特性,它允许根据不同的条件和场景在 SQL 语句中动态地组合和构建部分语句
< if>标签
我们在注册用户的时候,可能会有一个问题注册有两个字段
必填字段和非必填字段,这时我们需要使用动态标签来判定
例如:
添加性别为gender为非必填字段
定义接口
Integer insertUserByCondition(UserInfo userInfo);
实现xml
<insert id="insertUserByCondition">
insert into userinfo(username,
password,
age,
<if test="gender != null">
gender,
</if>
phone)
values (
#{username},
#{age},
<if test="gender != null">
#{gender},
</if>
#{phone})
</insert>
测试
当我们输入gender时 数据能正常插入
@Test
void testInsertUserByCondition() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("zhangfei");
userInfo.setPassword("123456");
userInfo.setAge(12);
userInfo.setGender(1);
userInfo.setPhone("12345678911");
Integer re = userInfoXMLMapper.insertUserByCondition(userInfo);
if (re>0){
log.info("插入成功!");
}
}
当我们不输入gender时会有
@Test
void testInsertUserByCondition() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("zhangfei");
userInfo.setPassword("123456");
userInfo.setAge(12);
//userInfo.setGender(1);
userInfo.setPhone("12345678911");
Integer re = userInfoXMLMapper.insertUserByCondition(userInfo);
if (re>0){
log.info("插入成功!");
}
}
我们可以看到sql语句变成了
insert into userinfo(username,password,age, phone) values (?,?,?, ?)
注意:
< trim>标签
之前的插⼊⽤⼾功能,只是有⼀个 gender 字段可能是选填项,如果有多个字段,⼀般考虑使⽤标签结合标签,对多个字段都采取动态⽣成的⽅式。
这个标签可以帮助我们去除多余的字符
prefix:表⽰整个语句块,以prefix的值作为前缀
suffix:表⽰整个语句块,以suffix的值作为后缀
prefixOverrides:表⽰整个语句块要去除掉的前缀
suffixOverrides:表⽰整个语句块要去除掉的后缀
调整上面的xml:
<insert id="insertUserByCondition">
insert into userinfo
<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>
<if test="phone != null">
phone
</if>
</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>
<if test="#{phone} != null">
#{phone}
</if>
</trim>
</insert>
sql动态解析时 会第一个处理
基于 prefix 配置,开始部分加上 (
基于 suffix 配置, 结束部分加上 )
多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于suffixOverrides 配置去掉最后⼀个 ,
注意:
注意 < if test=“username !=null”> 中的 username 是传⼊对象的属性
< where>标签
传⼊的⽤⼾对象,根据属性做where条件查询,⽤⼾对象中属性不为 null 的,都为查询条件. 如username 为 “a”,则查询条件为 where username=“a”
原有sql
select * from userinfo where age = 18 and gender =1 and delete_flag = 0;
定义接口:
List<UserInfo> queryByCondition();
xml实现:
<select id="queryByCondition" resultType="com.example.mybatisdemo.demos.web.model.UserInfo">
select id, username, age, gender, phone, delete_flag, create_time,
update_time from userinfo
<where>
<trim prefixOverrides="and">
<if test="age != null">
and age = #{age}
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="deleteFlag != null">
and delete_flag = #{deleteFlag}
</if>
</trim>
</where>
</select>
结果:
< where> 只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或OR 以上标签也可以使⽤ < trim
prefix=“where” prefixOverrides=“and”> 替换, 但是此种 情况下, 当⼦元素都没有内容时,
where关键字也会保留
< set>标签
需求: 根据传⼊的⽤⼾对象属性来更新⽤⼾数据,可以使⽤标签来指定动态内容
定义接口:传入的用户id属性 修改其他不为null属性
Integer updateUserByCondition(Integer id);
xml实现
<update id="updateUserByCondition">
update userinfo
<set>
<if test="age != null">
and age = #{age}
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="deleteFlag != null">
and delete_flag = #{deleteFlag}
</if>
</set>
where id = #{id}
</update>
< set> :动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号. (⽤于update语句中) 以上标签也可以使⽤ < trim
prefix=“set” suffixOverrides=“,”> 替换。
结果:
< foreach>标签
对集合进⾏遍历时可以使⽤该标签。标签有如下属性:
属性 | 说明 |
---|---|
collection | 绑定⽅法参数中的集合,如 List,Set,Map或数组对象 |
item | 遍历时的每⼀个对象 |
open | 语句块开头的字符串 |
close | 语句块结束的字符串 |
separator | 每次遍历之间间隔的字符串 |
需求根据多个userid删除用户数据
表的信息
接口方法
void deleteByIds(List<Integer> ids);
xml实现
<delete id="deleteByIds">
delete from userinfo
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
@Test
void deleteByIds() {
userInfoXMLMapper.deleteByIds(Arrays.asList(12,11,10));
}
结果
遇到的错误:
如果我们不加@Param(“ids”)
会报出类似: