动态SQL
概述
MyBatis的动态SQL包括以下几种元素:
元素 | 作用 | 备注 |
---|---|---|
if | 判断语句 | 单条件分支判断 |
choose(when, otherwise) | 相当于Java种的switch和case语句 | 多条件分支判断 |
trim(where, set) | 辅助元素,用于处理特定的SQL拼装问题,比如去掉多余的and、or等 | 用户处理SQL拼装的问题 |
foreach | 循环语句 | 在in语句等列举条件常用 |
if元素
if元素是最常用的判断语句,它常常与test属性联合使用。使用if构建动态SQL语句如下:
<select id="findRole" parameterType="string" resultMap="roleResultMap">
select role_no, role_name, note from t_role where 1=1
<if test="roleName!=null and roleName!=''">
and role_name like concat('%',#{roleName},'%')
</if>
</select>
choose、when、otherwise元素
在映射器的动态语句种choose、when、otherwise这三个元素承担了多种选择的功能。示例如下:
<select id="findRole" parameterType="string" resultMap="roleResultMap">
select role_no, role_name, note from t_role
where 1=1
<choose>
<when test="roleNo!=null and roleNo!=''">
AND role_no = #{roleNo}
</when>
<when test="roleName!=null and roleName !=''">
AND role_name like concat('%', #{roleName},'%')
</when>
<otherwise>
AND note is not null
</otherwise>
</choose>
</select>
trim、where、set元素
加入条件“1=1”是显得很奇快,可以用where元素去处理SQL以达到预期效果。示例如下:
<select id="findRole" parameterType="string" resultMap="roleResultMap">
select role_no, role_name, note from t_role
<where>
<if test="roleName!=null and roleName!=''">
AND role_name like concat('%', #{roleName},'%')
</if>
<if test="roleName!=null and roleName !=''">
AND note like concat('%', #{note},'%')
</if>
</where>
</select>
当where元素里面的条件成立,才会加入where这个SQL关键字到组装的SQL里面,否则就不加入。
trim元素可以去掉一些特殊的SQL语法,比如常见的and、or等。示例如下:
<select id="findRoles" parameterType="string" resultMap="roleResultMap">
select role_no, role_name, note from t_role
<trim prefix="where" prefixOverride="and">
<if test="roleName!=null and roleName!=''">
AND role_name like concat('%', #{roleName},'%')
</if>
</trim>
</select>
trim元素意味着要去掉一些特殊的字符串,当prefix代表的是语句的前缀,而prefixOverride代表的是需要去掉哪种字符串。
在MyBatis种,常常可以使用set元素避免发送所有的字段给持久对象。示例如下:
<update id="updateRole" parameterType="role">
update t_role
<set>
<if test="roleName != null and roleName != ''">
role_name = #{roleName}
</if>
<if test = "note != null and note != ''">
note = #{note}
</if>
</set>
</update>
set元素遇到了逗号,它会把对应的逗号去掉。
foreach元素
foreach元素是一个循环语句,他的作用是遍历集合,它能够很好地支持数组和List、Set接口的集合,对此提供遍历功能。它往往用于SQL中的in关键字。示例如下:
<select id ="findUserBySex" resultType="user">
select * from t_role where role_no in
<foreach item = "roleNo" index="index" collection="roleNoList" open="("separator="," close=)">
#{roleNo}
</foreach>
</select>
其中:
- collection配置的roleNoList是传递进来的参数名,可以是一个数组、List、Set等集合
- item配置的是循环中当前的元素
- index配置的是当前元素在集合的位置下标
- open和close配置的是以什么符号将这些集合元素包装起来
- separator是各个元素的间隔符
用test的属性判断字符串
test用于条件判断语句,在MyBatis中使用广泛。示例如下:
<select id="getRoleTest" parameterType="string" resultMap="roleResultMap">
select role_no, role_name, note from t_role
<if test="type == 'Y'.toString()">
where 1=1
</if>
</select>
如果把type='Y’传递给SQL,就可以发现MyBatis加入了条件where 1=1。
bind元素
bind元素的作用是通过OGNL表达式去自定义一个上下文变量,在进行模糊查询时,如果是MySQL数据库,常常用到的是一个concat,它用"%"和参数相连,如果是Oracle,则用连接符号“||”,这样需要提供两种形式,有了bind元素,就不必使用数据库语言,而是使用MyBatis的动态SQL即可完成。示例如下:
<select id="findRole" parameterType="string" resultMap="com.learn.ssm.mybatis.bean.RoleBean">
<bind name="pattern" value = "'%'+_parameter+'%'"/>
select id, role_name as roleName, create_date as createDate, end_date as endDate, end_flag as endFlag, note
from t_role where role_name like #{pattern}
</select>
这里的“_parameter”代表传递进来的参数,它和通配符(%)连接后赋给了pattern,然后就可以在select语句中使用这个变量进行模糊查询了。
MyBatis支持多个参数值使用bind元素的用法,传递多个参数前,首先定义接口方法:
public List<RoleBean> findRole(@Param("roleName") String roleName, @Param("note") String note);
定义映射文件和两个新的变量,然后执行模糊查询,如下所示:
<select id="findRole" resultMap="com.learn.ssm.mybatis.bean.RoleBean">
<bind name="pattern_roleName" value = "'%'+_roleName+'%'"/>
<bind name="pattern_note" value="'%'+ note + '%'"/>
select id, role_name as roleName, create_date as createDate, end_date as endDate, end_flag as endFlag, note
from t_role where role_name like #{pattern_roleName} and note like #{pattern_note}
</select>
这里绑定了两个新的变量pattern_roleName和pattern_note,这样就可以在SQL的其他地方使用了。