MyBatis where、set、trim
1. 前言
在前面的小節(jié)中,我們一起學習了 if 標簽,在通過 if 判斷動態(tài)插入或查詢的時候容易產(chǎn)生多余的前綴(如 WHERE)或后綴(如 , ),為了解決這類問題 MyBatis 提供了 where、set、trim 三個實用的標簽。
其中 where 和 set 標簽都是 trim 標簽的一種特殊情況,不過使用頻率非常高,因此被單獨定義成了標簽。本小節(jié)我們將一起來學習它們。
2. 定義
慕課解釋:
where
、set
、trim
三個標簽都是為了解決 MyBatis 在動態(tài)生成 SQL 時,產(chǎn)生了多余的前綴和后綴的問題。
3. 實例
3.1 where 實例
<select id="selectUserByIdAndName" resultType="com.imooc.mybatis.model.User">
SELECT * FROM imooc_user
<where>
<if test="id != null">
id = #{id}
</if>
<if test="username != null">
AND username = #{username}
</if>
</where>
</select>
在這個例子中,id 和 username 均非固定的過濾參數(shù),只有當其不為 null 時才會加入到 SQL 語句中。此處 where 標簽的作用大概有如下 3 個:
- 在 id 和 username 都為空的情況下,where 標簽不會產(chǎn)生任何 SQL 代碼段,最后的 SQL 語句為:
SELECT * FROM imooc_user
; - 在 id 不為空,username 為空的情況下,或者在 id 不為空,username 也不為空的情況下,where 標簽會自動給 SQL 代碼段添加上 WHERE 前綴;
- 在 id 為空,username 不為空的情況下,where 標簽會自定去除 AND 前綴,此時生成的 SQL 語句為:
SELECT * FROM imooc_user WHERE username = ?
。
3.2 set 實例
<update id="updateUsernameAndScoreById">
UPDATE imooc_user
<set>
<if test="username != null">
username = #{username},
</if>
id = #{id}
</set>
WHERE id = #{id}
</update>
set 標簽會自動在 SQL 語句中添加上相應的 SET 前綴,并根據(jù)里面的條件動態(tài)地添加相應的字段。
由于 SQL update 的語法問題,若 set 標簽里面條件均不滿足,此時 set 標簽也不會添加上 SET 前綴,但此時 SQL 會報語法錯誤,所以 set 標簽中還是得有一個必然存在的賦值。
3.3 trim 實例
<update id="updateUsernameAndScoreById">
UPDATE imooc_user
<trim prefix="SET" suffixOverrides=",">
<if test="username != null">
username = #{username},
</if>
<if test="id != null">
id = #{id}
</if>
</trim>
WHERE id = #{id}
</update>
這里的 trim 實例實現(xiàn)了與 set 實例同樣的功能,set 標簽是 trim 標簽的一種特殊情況。
trim 標簽共有 4 個屬性,它們的作用分別如下:
- prefix: 前綴屬性,若標簽內(nèi)不為空則在 SQL 中添加上前綴;
- prefixOverrides: 前綴覆蓋屬性,若標簽中有多余的前綴,將會被覆蓋(其實就是丟棄該前綴);
- suffix: 后綴屬性,若標簽內(nèi)不為空則在 SQL 中添加上后綴;
- suffixOverrides: 后綴覆蓋屬性,若標簽中有多余的后綴,將會被覆蓋(其實就是丟棄該后綴)。
這個例子中,trim 標簽的前綴為SET
,后綴覆蓋屬性為,
,所以在標簽內(nèi)不為空的情況下給 SQL 語句添加了 SET 關鍵字,且標簽內(nèi)若有多余的,
后綴也會被丟棄。
4. 實踐
4.1 例1. 動態(tài)插入用戶
請使用 MyBatis 完成對 imooc_user 表動態(tài)插入用戶的功能,若用戶屬性值不為 null 則插入該字段,否則不插入字段。
分析:
按照 MyBatis 的開發(fā)模式,先在 UserMapper.xml 文件中添加動態(tài)插入用戶的 insert 標簽,然后在 UserMapper.java 中添加上對應的方法。
步驟:
首先,在 UserMapper.xml 中添加 insert 標簽,并在標簽中寫入 SQL,使用 trim 標簽來動態(tài)判斷屬性是否為空,若不為空則插入該字段。
<insert id="insertUserDynamic" parameterType="com.imooc.mybatis.model.User">
INSERT INTO imooc_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">
username,
</if>
<if test="age != null">
age,
</if>
<if test="score != null">
score,
</if>
</trim>
VALUES
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">
#{username},
</if>
<if test="age != null">
#{age},
</if>
<if test="score != null">
#{score},
</if>
</trim>
</insert>
這里,我們使用了兩個 trim 標簽,一個用來動態(tài)寫入字段名,另一個用來動態(tài)寫入字段值;trim 標簽的前綴為(
,后綴為)
,當出現(xiàn)多余的,
時,會通過后綴覆蓋屬性來丟棄。
然后在 UserMapper.java 中添加上對應的接口方法:
package com.imooc.mybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.imooc.mybatis.model.User;
@Mapper
public interface UserMapper {
int insertUserDynamic(User user);
}
結果:
通過如下代碼,我們運行 insertUserDynamic 這個方法。
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("dynamic");
user.setScore(100);
int rows = userMapper.insertUserDynamic(user);
System.out.println(rows);
成功后,結果為:
1
TIPS: 注意,在 username、score 和 age 均為 null 時, insertUserDynamic 會報 SQL 語法錯誤,但理論上若是所有屬性均為空,那么也不應該插入。
5. 小結
- where、set 以及 trim 將 MyBatis 的動態(tài) SQL 發(fā)揮到了極致,為開發(fā)者節(jié)省了大量的精力和時間。
- trim 標簽是 MyBatis 中最為強大的一個標簽,使用它可以方便的完成 SQL 動態(tài)插入和動態(tài)更新。