MyBatis choose 和 bind
1. 前言
在上一小節(jié)中,我們介紹了 MyBatis 動態(tài) SQL 中最基礎(chǔ)的標(biāo)簽——if 標(biāo)簽,本小節(jié)我們將一起學(xué)習(xí) choose 和 bind 標(biāo)簽。
choose 標(biāo)簽是 if 標(biāo)簽的增強(qiáng)版,適用于更加復(fù)雜的條件判斷邏輯;而bind 標(biāo)簽則可以在 OGNL 上下文環(huán)境中新綁定一個變量,供后面的 SQL 使用。
2. 定義
慕課解釋:
choose
標(biāo)簽相當(dāng)于編程語言 if…else 語句,用于動態(tài) SQL 中的多條件判斷,是 if 標(biāo)簽的增強(qiáng)版。
bind
標(biāo)簽可以在動態(tài) SQL 中通過 OGNL 表達(dá)式來創(chuàng)建一個新的變量綁定到上下文中,供后續(xù)的 SQL 使用。
3. 實例
下面是一個融合了 choose 和 bind 標(biāo)簽的實例:
<select id="selectUserByLikeName" resultType="com.imooc.mybatis.model.User">
SELECT * FROM imooc_user
WHERE username LIKE
<choose>
<when test="_databaseId == 'mysql'">
CONCAT('%',#{username},'%')
</when>
<when test="_databaseId == 'postgre'">
'%' || #{username} || '%'
</when>
<otherwise>
<bind name="usernameLike" value="'%' + username + '%'"/>
#{usernameLike}
</otherwise>
</choose>
</select>
通過 choose 標(biāo)簽來判斷當(dāng)前的數(shù)據(jù)庫廠商,如果是 MySQL 數(shù)據(jù)庫,則調(diào)用CONCAT
函數(shù)來拼接 % 和 username,如果是 PostgreSQL 數(shù)據(jù)庫,則使用操作符||
來拼接,如果是其它類型的數(shù)據(jù)庫,則直接通過 OGNL 表達(dá)式來綁定一個新的變量 usernameLike。
在這個例子中,choose 是一個條件選擇標(biāo)簽,第一個 when 相當(dāng)于 if 判斷,第二個 when 相當(dāng)于 else if,最后的 otherwise 相當(dāng)于 else。比起 if 標(biāo)簽,choose 標(biāo)簽無疑更為易用,適用于同一條件的多次判斷邏輯。
4. 實踐
4.1 例1. 多條件查詢用戶
請使用 MyBatis 完成對 imooc_user 表多條件查詢用戶的功能,如果 id 不為空則直接使用 id 查詢用戶,否則使用 username 查詢用戶,如果 username 也為空,則直接查詢?nèi)坑脩簟?/p>
分析:
按照 MyBatis 的開發(fā)模式,需先在 UserMapper.xml 文件中添加多條件查詢用戶的 select 標(biāo)簽,然后在 UserMapper.java 中添加上對應(yīng)的方法。
步驟:
首先,在 UserMapper.xml 中添加 select 標(biāo)簽,并在標(biāo)簽中寫入 SQL,使用 choose 中的 when 標(biāo)簽來依次判斷 id 和 username 是否為 null,若均為 null,則在 otherwise 中添加上一個永假的值。如下:
<select id="selectUserByIdOrName" resultType="com.imooc.mybatis.model.User">
SELECT * FROM imooc_user
WHERE
<choose>
<when test="id != null">
id = #{id}
</when>
<when test="username != null">
username = #{username}
</when>
<otherwise>
1 = 0
</otherwise>
</choose>
</select>
這里使用了1 = 0
作為條件判斷的永假值。
然后在 UserMapper.java 中添加上對應(yīng)的接口方法,方法接受 id 和 username 兩個參數(shù),都可為空。
package com.imooc.mybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.imooc.mybatis.model.User;
@Mapper
public interface UserMapper {
User selectUserByIdOrName(@Param("id") Integer id, @Param("username") String username);
}
結(jié)果:
通過如下代碼,我們運(yùn)行 selectUserByIdOrName 這個方法。
UserMapper userMapper = session.getMapper(UserMapper.class);
User pedro = userMapper.selectUserByIdOrName(null, null);
System.out.println(pedro);
id 和 username 兩個屬性均為空,因此所執(zhí)行的 SQL 為:
SELECT * FROM imooc_user WHERE 1 = 0
成功后,結(jié)果為:
null
4.2 例2. 查詢小寫名稱客戶
請使用 MyBatis 完成對 imooc_user 表查詢小寫名稱客戶的功能,將名稱小寫后再進(jìn)行查詢。
分析:
同上。
步驟:
首先,在 UserMapper.xml 中添加 select 標(biāo)簽,并在標(biāo)簽中寫入 SQL,使用 bind 標(biāo)簽將參數(shù)小寫化成一個新的變量 lowercaseName。
<select id="selectUsernameLowercase" resultType="com.imooc.mybatis.model.User">
<bind name="lowercaseName" value="username.toLowercase"/>
SELECT * FROM imooc_user
WHERE username = #{lowercaseName}
</select>
然后在 UserMapper.java 中添加上對應(yīng)的接口方法,方法接受 username 一個參數(shù)。
package com.imooc.mybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.imooc.mybatis.model.User;
@Mapper
public interface UserMapper {
User selectUsernameLowercase(String username);
}
結(jié)果:
通過如下代碼,我們運(yùn)行 selectUsernameLowercase 這個方法。
UserMapper userMapper = session.getMapper(UserMapper.class);
User pedro = userMapper.selectUsernameLowercase("PEDRO");
System.out.println(pedro);
成功后,結(jié)果為:
User{id=2, username='pedro', age=24, score=200}
5. 小結(jié)
- bind 標(biāo)簽雖然可以通過 OGNL 表達(dá)式在上下文中綁定一個新的變量,但在實際應(yīng)用所見不多,我們希望在代碼層面上處理好參數(shù),這樣既方便維護(hù),也更有利于遷移。
- choose 標(biāo)簽是一個增強(qiáng)版的 if 標(biāo)簽,適用于更加復(fù)雜的邏輯判斷場景。