MyBatis-Plus 中 的動(dòng)態(tài)SQL 片段(sqlSegment)詳解
以下是針對(duì) MyBatis-Plus 中 通用 SQL 片段(sqlSegment) 的清晰詳解,結(jié)合核心功能與實(shí)用場(chǎng)景,逐步說(shuō)明其用法:
一、什么是sqlSegment?
在 MyBatis-Plus 中,sqlSegment 通常指 動(dòng)態(tài)生成的 SQL 代碼塊,例如由條件構(gòu)造器(Wrapper)自動(dòng)生成的 WHERE 條件、ORDER BY 排序等。開(kāi)發(fā)者可通過(guò)特定語(yǔ)法(如 ${ew.customSqlSegment}或者${ew.sqlSegment})將這些片段插入到自定義 SQL 中,實(shí)現(xiàn)靈活組合。
二、核心使用方式
1.條件構(gòu)造器(Wrapper)動(dòng)態(tài)生成 SQL 片段
通過(guò) QueryWrapper 或 LambdaQueryWrapper 構(gòu)建條件,自動(dòng)生成 WHERE 后的條件語(yǔ)句。
// 創(chuàng)建 Wrapper
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", 1)
.like("username", "Tom")
.orderByDesc("create_time");
// 執(zhí)行查詢(自動(dòng)拼接條件到 SQL)
List<User> users = userMapper.selectList(wrapper);生成 SQL:
SELECT * FROM user WHERE status = 1 AND username LIKE '%Tom%' ORDER BY create_time DESC
2.在 XML 中引用 Wrapper 的 SQL 片段
使用 ${ew.customSqlSegment} 占位符,將 Wrapper 中的條件插入到自定義 SQL。
<!-- XML 映射文件 -->
<select id="selectByWrapper" resultType="User">
SELECT * FROM user
WHERE age > 18
${ew.customSqlSegment} <!-- 插入 Wrapper 的條件 -->
</select>Java 調(diào)用:
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ne("email", null); // 添加條件:email IS NOT NULL
List<User> users = userMapper.selectByWrapper(wrapper);生成 SQL:
SELECT * FROM user WHERE age > 18 AND email IS NOT NULL <!-- 來(lái)自 Wrapper -->
三、關(guān)鍵語(yǔ)法解析
1.${ew.customSqlSegment}的作用
ew是 MyBatis-Plus 的固定參數(shù)名,代表Wrapper對(duì)象。customSqlSegment是Wrapper中生成的 SQL 片段(如WHERE條件、ORDER BY)。- 注意:必須確保
Wrapper對(duì)象作為參數(shù)傳遞到 XML 中(通常參數(shù)名為ew)。
2.Lambda 表達(dá)式避免硬編碼字段名
使用 LambdaQueryWrapper 提升代碼安全性和可讀性:
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(User::getStatus, 1) // 方法引用代替字符串
.ge(User::getAge, 18)
.orderByAsc(User::getCreateTime);3.${ew.customSqlSegment} 與 ${ew.sqlSegment} 的區(qū)別對(duì)比
1.${ew.customSqlSegment}:動(dòng)態(tài)拼接完整 WHERE 條件:常用于無(wú)需手動(dòng)編寫 WHERE 的自定義 SQL 中
2.${ew.sqlSegment}:僅注入條件表達(dá)式:需手動(dòng)拼接 WHERE,適用于需要精確控制 SQL 結(jié)構(gòu)的場(chǎng)景
// Mapper 接口
@Select("SELECT * FROM user ${ew.customSqlSegment}")
List<User> selectPageCustom(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
@Select("SELECT * FROM user WHERE ${ew.sqlSegment}")
List<User> selectPageWhere(@Param(Constants.WRAPPER) Wrapper<User> wrapper); 四、實(shí)際應(yīng)用場(chǎng)景
場(chǎng)景 1:動(dòng)態(tài)條件查詢
根據(jù)用戶輸入動(dòng)態(tài)拼接查詢條件,無(wú)需手動(dòng)編寫 if 判斷。
public List<User> searchUsers(String name, Integer minAge) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(name), User::getUsername, name)
.ge(minAge != null, User::getAge, minAge);
return userMapper.selectList(wrapper);
}like和ge方法中的第一個(gè)參數(shù)為條件布爾值,自動(dòng)決定是否拼接該條件。
場(chǎng)景 2:復(fù)用公共 SQL 片段
在 XML 中定義公共片段,結(jié)合 Wrapper 實(shí)現(xiàn)復(fù)用。
<!-- 定義公共的 WHERE 條件 -->
<sql id="activeUser">
is_deleted = 0 AND status = 'ACTIVE'
</sql>
<!-- 在查詢中復(fù)用 -->
<select id="selectActiveUsers" resultType="User">
SELECT * FROM user
WHERE <include refid="activeUser"/>
${ew.customSqlSegment} <!-- 追加其他動(dòng)態(tài)條件 -->
</select>Java 調(diào)用:
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("username", "Admin");
List<User> users = userMapper.selectActiveUsers(wrapper);生成 SQL:
SELECT * FROM user WHERE is_deleted = 0 AND status = 'ACTIVE' <!-- 公共片段 --> AND username LIKE '%Admin%' <!-- 動(dòng)態(tài)條件 -->
場(chǎng)景 3:邏輯刪除自動(dòng)過(guò)濾
配置 MyBatis-Plus 全局邏輯刪除,自動(dòng)在所有查詢中注入 WHERE is_deleted=0。
# application.yml
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDeleted # 實(shí)體類字段名
logic-delete-value: 1 # 刪除后的值
logic-not-delete-value: 0 # 未刪除的值- 無(wú)需手動(dòng)編寫條件,刪除操作自動(dòng)變?yōu)?
UPDATE語(yǔ)句,查詢自動(dòng)過(guò)濾已刪除數(shù)據(jù)。
五、最佳實(shí)踐與避坑指南
1.優(yōu)先使用 LambdaQueryWrapper
- 優(yōu)勢(shì):避免字段名硬編碼,編譯時(shí)檢查,重構(gòu)友好。
- 示例:
lambdaWrapper.eq(User::getStatus, 1) // 正確性由編譯器保證
2.謹(jǐn)慎使用${}防止 SQL 注入
- 安全寫法:
WHERE username = #{param} <!-- 使用 #{} 預(yù)編譯 --> - 風(fēng)險(xiǎn)寫法:
ORDER BY ${orderBy} <!-- 直接拼接字符串,需手動(dòng)過(guò)濾參數(shù) -->
3.復(fù)雜 SQL 結(jié)合 XML 片段
對(duì)于多表 JOIN 或復(fù)雜統(tǒng)計(jì),仍可在 XML 中編寫完整 SQL,利用 <include> 復(fù)用片段。
<select id="selectUserWithRole" resultType="map">
SELECT u.*, r.role_name
FROM user u
LEFT JOIN role r ON u.role_id = r.id
${ew.customSqlSegment}
</select>六、總結(jié)
- 核心機(jī)制:通過(guò)
Wrapper生成動(dòng)態(tài) SQL 片段,結(jié)合${ew.customSqlSegment}嵌入自定義 SQL。 - 適用場(chǎng)景:動(dòng)態(tài)條件查詢、邏輯刪除、多租戶隔離、公共代碼復(fù)用。
- 優(yōu)勢(shì):減少重復(fù)代碼、提升可維護(hù)性、保持 SQL 靈活性。
通過(guò)合理利用 MyBatis-Plus 的 SQL 片段功能,可顯著簡(jiǎn)化開(kāi)發(fā)流程,尤其適合快速迭代的中大型項(xiàng)目。
到此這篇關(guān)于MyBatis-Plus 中 的動(dòng)態(tài)SQL 片段(sqlSegment)講解的文章就介紹到這了,更多相關(guān)MyBatis-Plus動(dòng)態(tài)SQL內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot原生組件注入實(shí)現(xiàn)兩種方式介紹
SpringBoot是Spring全家桶的成員之一,基于約定優(yōu)于配置的思想(即有約定默認(rèn)值,在不配置的情況下會(huì)使用默認(rèn)值,在配置文件下配置的話會(huì)使用配置的值)。SpringBoot是一種整合Spring技術(shù)棧的方式(或者說(shuō)是框架),同時(shí)也是簡(jiǎn)化Spring的一種快速開(kāi)發(fā)的腳手架2022-10-10
SpringBoot通過(guò)JSON傳遞請(qǐng)求參數(shù)的實(shí)例詳解
這篇文章主要介紹了SpringBoot通過(guò)JSON傳遞請(qǐng)求參數(shù),示例介紹SpringMVC如何通過(guò)JSON格式傳遞入?yún)?,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-11-11
Java基礎(chǔ)類學(xué)習(xí)之String詳解
這篇文章主要為大家詳細(xì)介紹了Java基礎(chǔ)類中String的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下2022-12-12
關(guān)于SpringBoot大文件RestTemplate下載解決方案
這篇文章主要介紹了SpringBoot大文件RestTemplate下載解決方案,最近結(jié)合網(wǎng)上案例及自己總結(jié),寫了一個(gè)分片下載tuling/fileServer項(xiàng)目,需要的朋友可以參考下2021-10-10
java集合類arraylist循環(huán)中刪除特定元素的方法
下面小編就為大家?guī)?lái)一篇Java集合類ArrayList循環(huán)中刪除特定元素的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11
java 簡(jiǎn)單的計(jì)算器程序?qū)嵗a
這篇文章主要介紹了java 簡(jiǎn)單的計(jì)算器程序?qū)嵗a的相關(guān)資料,需要的朋友可以參考下2017-06-06
JavaWeb開(kāi)發(fā)實(shí)現(xiàn)備忘錄
這篇文章主要為大家詳細(xì)介紹了JavaWeb開(kāi)發(fā)實(shí)現(xiàn)備忘錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06

