在mybatis的xml文件中構建動態sql語句時,經常會用到標簽遍歷查詢條件。特此記錄下不同情況下書寫方式!-------僅供大家參考------
1. foreach元素的屬性
- collection: 需做foreach(遍歷)的對象,作為入參時,list、array對象時,collection屬性值分別默認用"list"、"array"代替,Map對象沒有默認的屬性值。但是,在作為入參時可以使用@Param(“keyName”)注解來設置自定義collection屬性值,設置keyName后,list、array會失效;
- item: 集合元素迭代時的別名稱,該參數為必選項;
- index: 在list、array中,index為元素的序號索引。但是在Map中,index為遍歷元素的key值,該參數為可選項;
- open: 遍歷集合時的開始符號,通常與close=")"搭配使用。使用場景IN(),values()時,該參數為可選項;
- separator: 元素之間的分隔符,類比在IN()的時候,separator=",",最終所有遍歷的元素將會以設定的(,)逗號符號隔開,該參數為可選項;
- close: 遍歷集合時的結束符號,通常與open="("搭配使用,該參數為可選項;
2.foreach時,collection屬性值的三種情況:
- 如果傳入的參數類型為List時,collection的默認屬性值為list,同樣可以使用@Param注解自定義keyName;
- 如果傳入的參數類型為array時,collection的默認屬性值為array,同樣可以使用@Param注解自定義keyName;
- 如果傳入的參數類型為Map時,collection的屬性值可為三種情況:(1.遍歷map.keys;2.遍歷map.values;3.遍歷map.entrySet()),稍后會在代碼中示例;
3.代碼示例:
3.1 collection屬性值類型為List:
Mapper接口定義的方法:UserList為模擬返回的數據對象
List<UserList> getUserInfo(@Param("userName") List<String> userName);
Mapper.xml 動態sql構建,Mapper接口的方法名和xml文件的id值,必須一一對應,否則會報錯:
-----建議做if test="xxxx !=null and xxxx.size()>0"的校驗,比較嚴謹。array為.length();
<select id="getUserInfo" resultType="com.test.UserList">
SELECT
*
FROM user_info
where
<if test="userName!= null and userName.size() >0">
USERNAME IN
<foreach collection="userName" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</if>
</select>
3.2 collection屬性值類型為Array:
Mapper接口定義的方法:UserList為模擬返回的數據對象
List<UserList> getUserInfo(@Param("userName") String[] userName);
Mapper.xml 動態sql構建,Mapper接口的方法名和xml文件的id值,必須一一對應,否則會報錯:
-----建議做if test="xxxx !=null and xxxx.length()>0"的校驗,比較嚴謹。
<select id="getUserInfo" resultType="com.test.UserList">
SELECT
*
FROM user_info
where
<if test="userName!= null and userName.length() >0">
USERNAME IN
<foreach collection="userName" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</if>
</select>
3.3 collection屬性值類型為Map:
近期在項目中,遇到這樣一個需求,sql查詢的條件之一是兩個字段確定唯一的一個人,並且條件可能是多個人或者一個人。以往開發中,我們可能遇到只有一個字段的集合或者數組。進入正題:
接收前台傳遞的List,組裝查詢條件。其實也可以直接傳一個List對象集合,但是實際開發中,List中的每一個對象包含了幾十個字段,而我們只需要其中的兩個,所以我選擇數據組裝傳遞。
實現類處理:
Map<String, String> patientMap = userList.stream().filter(item -> StringUtils.hasText(item.getUserName()) &&
StringUtils.hasText(item.getAge())).collect(Collectors.toMap(UserList::getUserName, UserList::getAge));
Mapper接口定義的方法:UserList為模擬返回的數據對象
List<UserList> getUserInfo(@Param("user") Map<String,String> user);
Mapper.xml 動態sql構建,Mapper接口的方法名和xml文件的id值,必須一一對應,否則會報錯:
-----建議做 if test="xxxx !=null and xxxx.size()>0"的校驗,比較嚴謹。
第一種:獲取Map的鍵值對,多字段組合條件情況下,一定要注意書寫格式:括號()
eg: SELECT * FROM user_info WHERE (USERNAME,AGE) IN (('張三','26'),('李四','58'),('王五','27'),......);
<select id="getUserInfo" resultType="com.test.UserList">
SELECT
*
FROM user_info
where
<if test="user!= null and user.size() >0">
(USERNAME,AGE) IN
<foreach collection="user.entrySet()" item="value" index="key" separator="," open="(" close=")">
(#{key},#{value})
</foreach>
</if>
</select>
第二種:參數Map類型,只需要獲取key值或者value值
key:
<select id="getUserInfo" resultType="com.test.UserList">
SELECT
*
FROM user_info
where
<if test="user!= null and user.size() >0">
(USERNAME) IN
<foreach collection="user.keys" item="key" separator="," open="(" close=")">
#{key}
</foreach>
</if>
</select>
value:
<select id="getUserInfo" resultType="com.test.UserList">
SELECT
*
FROM user_info
where
<if test="user!= null and user.size() >0">
(USERNAME) IN
<foreach collection="user.values" item="value" separator="," open="(" close=")">
#{key}
</foreach>
</if>
</select>