動態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的其他地方使用了。