文章目录
- 动态sql
- if
- choose(when、otherwise)
- trim(where、set)
- foreach
- sql片段
动态sql
动态SQL是MyBatis的强大特性之一,利用动态SQL,我们能根据不同条件灵活的拼接SQL语句。常用的动态SQL标签有如下几种:
- if
- choose(when、otherwise)
- trim(where、set)
- foreach
if
使用<if>sql</if>时,如果满足条件,则会将sql和前面的sql片段拼接起来,示例如下:
<select id="selectStudentIf" resultType="com.example.entity.Student">
select * from student
where 1 = 1
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age > 0">
and age > #{age}
</if>
</select>
如果name的值为null,或者值为空字符串,则and name = #{name}
sql片段将不会与前文sql拼接,如果上述例子的两个条件均满足,则最终形成的sql语句为:
select * from student where 1 = 1 and name = #{name} and age > #{age}
注意事项
:在上述例子中,我们第一次看时不免会感到疑惑,1 = 1
这个条件不是多余的吗?其实,仔细思考后,我们会发现,如果去掉该条件,当第一个条件不满足时(即name值为null或者为空字符串),形成的sql语句为:
select * from student where and age > #{age}
显然,该sql语句是存在错误的,and
应该去除,如果加上在and
前加上一个恒成立的条件,就可以解决这个问题,此外,我们还可以借助<where>来解决这个问题(见下文)。
choose(when、otherwise)
<choose>有点类似switch-case,使用该标签,会从多个条件中选择一个使用,示例如下:
<select id="selectStudentIf" resultType="com.example.entity.Student">
select * from student
where 1 = 1
<choose>
<!-- 条件1 -->
<when test="name != null and name != ''">
and name = #{name}
</when>
<!-- 条件2 -->
<when test="age > 0">
and age > #{age}
</when>
<otherwise>
and id < #{id}
</otherwise>
</choose>
</select>
如上所示,可分为三种情况:
- 条件1、2均满足,结果选择条件1中的sql语句,最终结果为:
select * from student where 1 = 1 and name = #{name}
- 条件1、2中只有其中一个满足时,选择满足条件中的sql语句,最终结果为:
<!-- 条件1满足 -->
select * from student where 1 = 1 and name = #{name}
<!-- 条件2满足 -->
select * from student where 1 = 1 and age > #{age}
- 条件1、2均不满足时,选择<otherwise>中的sql语句(如果使用了该标签),最终结果为:
select * from student where 1 = 1 and id < #{id}
trim(where、set)
- where
使用<where>,能够解决我们在上文if标签示例中提到的问题,示例如下:
<select id="selectStudentWhere" resultType="com.example.entity.Student">
select * from student
<where>
<!-- 条件1 -->
<if test="name != null and name != ''">
name = #{name}
</if>
<!-- 条件2 -->
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
当条件1不满足,条件2满足时,最终结果为:
select * from student where age > #{age}
此时不会再出现多余的and | or
,where标签自动为我们去除了多余的and
或者or
,得到正确的sql语句。
- set
<update id="updateSet">
update student
<set>
<if test="name != null">name = #{name},</if>
<if test="age > 0">age = #{age},</if>
<!-- 条件3 -->
<if test="email != null">email = #{email}</if>
</set>
where id = #{id}
</update>
如上述例子,如果条件3不满足,前两个条件至少有1个满足时,则最终的sql语句会出现多余的,
,使用<set>则能够去除多余的逗号,得到正确的sql语句。
- trim
如果上述的where
和set
标签结果与我们的期望不同,可以通过自定义trim
标签来定制where和set标签的功能,例如,和where、set标签等价的自定义trim标签分别如下:
<trim prefix="WHERE" prefixOverrides="AND | OR">
...
</trim>
<trim prefix="SET" suffixOverrides=",">
...
</trim>
foreach
foreach标签在对集合进行遍历的场景下使用(例如:in条件语句),示例如下:
<select id="selectForeachOne" resultType="com.example.entity.Student">
select * from student where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</select>
如果遍历的集合中的元素是自定义的类,例如:List<Student>,item=“stu”,使用id属性的值时,则#{myid}改为#{stu.id}即可。
foreach标签中各属性值说明:
collection:表示接口中的方法参数的类型,如果是数组,使用array,如果是list则使用list
item:自定义,表示数组和集合成员的变量
open:循环开始时的字符
close:循环结束时的字符
separator:集合成员之间的分隔符
sql片段
步骤:
- 先定义<sql id=“自定义名称(唯一)”> sql语句,表名,字段等</sql>
- 再使用<include refid=“id的值”/>
示例如下:
<sql id="studentSql">
select * from student
</sql>
<!-- 使用 -->
<select id="selectStudentIf" resultType="com.example.entity.Student">
<include refid="studentSql"/>
...
</select>