MyBatis动态SQL
半塘 2024/1/12 MyBatis框架
动态 SQL 是 MyBatis 的强大特性之一。可以根据不同条件拼接 SQL ,让我们将关注点在业务上,拼接SQL体现了易用性。
# 1、if
条件满足,拼接条件
Mapper接口新增方法
List<UserPO> selectUserByName3(@Param("name") String name);
1
Mapper.xml映射
<select id="selectUserByName3" resultType="com.xygalaxy.pojo.UserPO">
select * from user where 1=1
<if test="name!=null and name!=''">
and username like CONCAT('%', #{name}, '%')
</if>
</select>
1
2
3
4
5
6
2
3
4
5
6
测试
@Test
public void testExecutorInterceptor(){
List<UserPO> userPOList = userMapper.selectUserByName3("");
log.info("userPOList ==> "+userPOList);
List<UserPO> userPOList2 = userMapper.selectUserByName3("ls");
log.info("userPOList2 ==> "+userPOList2);
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
测试结果
- test 中为条件表达式
- if拼接语句中的and,如果多余了,会自动去掉,比如第一个条件时,前面是不加and的,if标签会自动去掉
# 2、choose、when、otherwise
多个条件选择一个,类似Java中的switch
。
<select id="selectUserBy" resultType="com.xygalaxy.pojo.UserPO">
select * from user where 1=1
<choose>
<when test="id!=null and id!=''">
and id = #{id}
</when>
<when test="name!=null and name!=''">
and username like CONCAT('%', #{name}, '%')
</when>
<otherwise test="sex!=null and sex!=''">
and sex = #{sex}
</otherwise>
</choose>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
条件满足when时,拼接条件后,如果都不满足,则拼接最后一个otherwise中的条件。
# 3、trim、where、set
- where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<select id="selectUserByName3" resultType="com.xygalaxy.pojo.UserPO">
select * from user
<where>
<if test="name!=null and name!=''">
and username like CONCAT('%', #{name}, '%')
</if>
</where>
</select>
<!--
拼接结果: select * from user where username like CONCAT('%', #{name}, '%')
-->
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- trim 元素来定制拼接。
<select id="selectUserByName3" resultType="com.xygalaxy.pojo.UserPO">
select * from user
<trim prefix="where (" suffix=")" prefixOverrides="AND |OR ">
<if test="name!=null and name!=''">
and username like CONCAT('%', #{name}, '%')
</if>
</trim>
</select>
<!--
拼接结果: select * from user where ( username like CONCAT('%', #{name}, '%') )
-->
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- prefix属性表示要添加到SQL语句前面的字符串。在这个案例中,我们指定了一个左括号
where (
作为前缀。 - suffix属性表示要添加到SQL语句后面的字符串。在这个案例中,我们指定了一个右括号
)
作为后缀。 - prefixOverrides属性是一个正则表达式,用于删除SQL语句中指定的前缀。在这个案例中,我们使用了AND |OR,表示删除以AND或者OR开头的字符串。
- set用于动态更新语句的解决方案
<update id="updateUserById">
update user
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
</set>
where id=#{id}
</update>
<!-- 当然也可以用trim来实现,suffixOverrides用于删除最后一个, -->
<update id="updateUserById">
update user
<trim prefix="SET" suffixOverrides=",">
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
</trim>
where id=#{id}
</update>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 4、foreach
对集合进行遍历(尤其是在构建 IN 条件语句的时候)
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT * FROM user
<where>
<foreach item="item" index="index" collection="list"
open="ID in (" separator="," close=")" nullable="true">
#{item}
</foreach>
</where>
</select>
<!--
list传入为:1,2,3,4,5
拼接结果: SELECT * FROM user where ID in (1,2,3,4,5)
-->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- collection:传入的集合
- item:每一项遍历的值,index为集合索引下标
- open:开始拼接的字符串
- separator:每一项之间的分隔符
- close:结束拼接的字符串
# 6、script
注解的映射器接口类中使用动态 SQL时使用
@Update({"<script>",
"update user",
" <set>",
" <if test='username != null'>username=#{username},</if>",
" <if test='password != null'>password=#{password},</if>",
" <if test='email != null'>email=#{email},</if>",
" </set>",
"where id=#{id}",
"</script>"})
void updateUserById(UserPO userPO);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 7、bind
创建变量,绑定到当前的上下文
<select id="selectUserByName2" resultType="com.xygalaxy.pojo.UserPO">
select * from user
<where>
<bind name="currentName" value="'%'+name+'%'"/>
username like #{currentName}
</where>
</select>
1
2
3
4
5
6
7
2
3
4
5
6
7
# 8、selectKey
查询插入主键
<insert id="saveUser" parameterType="com.xygalaxy.pojo.UserPO">
<selectKey keyProperty="id" resultType="Integer" order="BEFORE">
select if(max(id) is null, 1, max(id) +1) as id from user
</selectKey>
insert into user(id,username,password,email) values(#{id},#{username},#{password},#{email})
</insert>
1
2
3
4
5
6
2
3
4
5
6