MyBatis動態SQL語句的關鍵字有:
if
choose (when, otherwise)
trim (where, set)
foreach
等類型。
MyBatis 採用功能強大的基於 OGNL 的表達式來消除其他元素。
拼接sql語句的好處在於,可以進行選擇性查詢,如果不傳遞參數則是進行全部查詢,如果有參數傳遞則是進行拼接到對應的sql上。
where 元素知道只有在一個以上的if條件有值的情況下才去插入“WHERE”子句。而且,若最後的內容是“AND”或“OR”開頭的,where 元素也知道如何將他們去除。
IF
IF語句的使用通常是有條件的 進行SQL語句的Where條件的查詢。所以注意【Where】標籤的使用。
<select id="findUserList" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
select * from user
<where>
<if test="userExtends!=null">
<if test="userExtends.sex!=null and userExtends.sex!=''">
and user.sex=#{userExtends.sex}
</if>
<if test="userExtends.username!=null and userExtends.username!='' ">
and user.username like '%${userExtends.username}%'
</if>
</if>
</where>
</select>
說明: 上述的SQL語句就是利用IF條件進行SQL語句的拼裝,這裏,利用IF標籤的test屬性進行條件的判斷,如果條件成立,則進行SQL語句拼裝,如果不成立則跳過此條件語句的拼裝。
解釋:當我們傳入的條件UserVo爲NULL時,則直接進行的語句爲“select * from user”;
如果我們UserVo不爲空時,然後我們又會分別判斷我們的sex和username是不是爲空或者null,如果都有值則會都進行拼接,此時的SQL語句爲:“select * from user where user.sex = ‘參數一’ and user.username like ‘%參數二%’ ”;
choose(when, otherwise)
choose的使用,主要是在多個條件下進行選擇匹配時使用,比如我們常說的在,兩個中選其中的一個條件,它有點像 Java 中的 switch 語句,只進行匹配條件成功的語句進行拼接。
<select id="findUserListChoose" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
select * from user
<where>
<choose>
<when test="userExtends.sex!=null and userExtends.sex!=''">
user.sex=#{userExtends.sex}
</when>
<when test="userExtends.username!=null and userExtends.username!=''">
and user.username like '%${userExtends.username}%'
</when>
<otherwise>
and 1=1
</otherwise>
</choose>
</where>
</select>
說明:上述的SQL則是在進行條件匹配,如果when標籤的條件進行匹配成功,那麼就進行拼接SQL語句,如果所有的when條件都不成立的情況下,則是進行otherwise匹配。
trim (where, set)
自定義 trim 元素是用來定製我們想要的功能。
1、由於我們的where元素知道只有在一個以上的if條件有值的情況下才去插入“WHERE”子句。而且,若最後的內容是“AND”或“OR”開頭的,where 元素也知道如何將他們去除。
這樣的話,我們可以利用我們的trim元素進行等價轉化。
<!-- trim 語法 -->
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
<!-- trim 配置 -->
<select id="findUserListtrim" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
select * from user
<trim prefix="where" prefixOverrides="AND |OR |String">
<if test="userExtends!=null">
<if test="userExtends.sex!=null and userExtends.sex!=''">
String user.sex=#{userExtends.sex}
</if>
<if test="userExtends.username!=null and userExtends.username!='' ">
and user.username like '%${userExtends.username}%'
</if>
</if>
</trim>
</select>
// 測試用例打印的語句
Preparing: select * from user where user.sex=? and user.username like '%張三%'
說明:prefixOverrides 屬性會忽略通過管道分隔的文本序列(注意此例中的空格也是必要的)。它帶來的結果就是所有在 prefixOverrides 屬性中指定的內容將被移除,並且插入 prefix 屬性中指定的內容。,此處是利用管道分隔符將我們的String字符進行替換成了 where字符。
set動態更新語句,set 元素可以被用於動態包含需要更新的列,而捨去其他的
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
<!-- 等價的trim語句 -->
<trim prefix="SET" suffixOverrides=",">
...
</trim>
foreach
foreach 元素的功能是非常強大的,它允許你指定一個集合,聲明可以用在元素體內的集合項和索引變量。它也允許你指定開閉匹配的字符串以及在迭代中間放置分隔符。這個元素是很智能的,因此它不會偶然地附加多餘的分隔符。通常是在構建 IN 條件語句的時候。
你可以將任何可迭代對象(如列表、集合等)和任何的字典或者數組對象傳遞給foreach作爲集合參數。當使用可迭代對象或者數組時,index是當前迭代的次數,item的值是本次迭代獲取的元素。當使用字典(或者Map.Entry對象的集合)時,index是鍵,item是值。
collection :傳遞參數對象中的集合屬性名
item : 集合中存放的變量別名,用在下面的引用
open :開始遍歷時拼接的字符串
close :結束遍歷時拼接的字符串
separator 遍歷的兩個對象中需要拼接的字符串
<select id="findUserList" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
select * from user
<where>
<include refid="usersql"></include>
</where>
</select>
<!-- sql語句片段引用 -->
<sql id="usersql">
<if test="userExtends!=null">
<if test="userExtends.sex!=null and userExtends.sex!=''">
and user.sex=#{userExtends.sex}
</if>
<if test="userExtends.username!=null and userExtends.username!='' ">
and user.username like '%${userExtends.username}%'
</if>
</if>
<!--sql : select * from user where name like '%張三' and id IN(17,18,19) -->
<if test="ids!=null">
<foreach collection="ids" item="user_id" open="and id in(" close=")" separator=",">
#{user_id}
</foreach>
</if>
</sql>
<!-- UserVo類 -->
public class UserVo {
private UserExtends userExtends;
private List<Integer> ids; /// 設置接受多個參數的ids
}
// 測試方法
@Test
public void testfindUserList() { // 測試foreach
SqlSession session = sqlsessionfactory.openSession();
UserDaoMapper userDaoMapper = session.getMapper(UserDaoMapper.class);
UserVo uservo = new UserVo();
UserExtends userExtends = new UserExtends();
userExtends.setSex("男");
//userExtends.setUsername("張三");
uservo.setUserExtends(userExtends);
List<Integer> list = new ArrayList<Integer>(); // 屬性設置
list.add(17);
list.add(18);
list.add(19);
uservo.setIds(list);
List<UserExtends> userList = userDaoMapper.findUserList(uservo);
for(UserExtends u :userList){
System.out.println(u.getUsername());
}
}
// 測試用例 打印SQL語句
Preparing: select * from user WHERE user.sex=? and id in( ? , ? , ? )