最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis實(shí)戰(zhàn)之動(dòng)態(tài)生成SQL詳解

 更新時(shí)間:2025年07月21日 09:24:57   作者:秋秋棠  
這篇文章主要為大家詳細(xì)介紹了如何使用MyBatis實(shí)現(xiàn)動(dòng)態(tài)生成SQL,可以告別硬編碼,擁抱智能SQL生成,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

在電商平臺(tái)的用戶管理模塊中,需要面對多種不同的用戶查詢組合條件。當(dāng)使用傳統(tǒng)的硬編碼SQL方式時(shí),代碼膨脹到了2000多行,維護(hù)成本極高。而引入MyBatis動(dòng)態(tài)SQL后,同樣的功能僅用300行代碼實(shí)現(xiàn),且可讀性提升了3倍——這就是動(dòng)態(tài)SQL的威力!

一、為什么需要?jiǎng)討B(tài)SQL

傳統(tǒng)SQL拼接的痛點(diǎn)

// 傳統(tǒng)方式需要手動(dòng)拼接SQL字符串
StringBuilder sql = new StringBuilder("SELECT * FROM user WHERE 1=1");
if (user.getId() != null) {
    sql.append(" AND id = ").append(user.getId());
}
if (user.getUsername() != null) {
    sql.append(" AND username = '").append(user.getUsername()).append("'");
}
// 存在SQL注入風(fēng)險(xiǎn)!且代碼冗長難維護(hù)

動(dòng)態(tài)SQL的核心價(jià)值

  • 消除重復(fù)代碼:相同業(yè)務(wù)邏輯不再需要重復(fù)編寫
  • 防止SQL注入:自動(dòng)使用預(yù)編譯參數(shù)
  • 提升可讀性:SQL與Java邏輯解耦
  • 降低出錯(cuò)率:避免手動(dòng)拼接錯(cuò)誤

二、動(dòng)態(tài)SQL核心標(biāo)簽解析

1.<if>標(biāo)簽:條件分支處理

業(yè)務(wù)場景:根據(jù)傳入?yún)?shù)動(dòng)態(tài)添加查詢條件

<select id="findUsers" parameterType="User" resultType="User">
    SELECT * FROM user
    <where>
        <if test="id != null">
            AND id = #{id}
        </if>
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="password != null">
            AND password = #{password}
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </where>
</select>

執(zhí)行原理

2.<where>標(biāo)簽:智能WHERE處理

自動(dòng)處理

  • 條件前多余的AND/OR
  • 當(dāng)所有條件都不滿足時(shí),移除WHERE關(guān)鍵字

錯(cuò)誤示例

<!-- 當(dāng)所有if都不滿足時(shí),SQL會(huì)變成:SELECT * FROM user WHERE -->
SELECT * FROM user
WHERE
    <if test="id != null">id = #{id}</if>

正確用法

SELECT * FROM user
<where>
    <if test="id != null">id = #{id}</if>
    <!-- 其他條件... -->
</where>

3. 其他核心標(biāo)簽

標(biāo)簽應(yīng)用場景示例片段
<choose>多選一邏輯(類似switch-case)<when test="...">...<otherwise>...
<foreach>遍歷集合(IN查詢等)item in #{ids} open="(" close=")"
<set>動(dòng)態(tài)更新語句更新時(shí)自動(dòng)處理SET后的逗號(hào)
<trim>自定義字符串修剪可替代where/set的更靈活方案

三、最佳實(shí)踐:用戶查詢案例

Java調(diào)用代碼

// 創(chuàng)建參數(shù)對象
User queryParams = new User();
queryParams.setId(1);
queryParams.setPassword("securePass123");

// 執(zhí)行動(dòng)態(tài)查詢
UserRepository repo = sqlSession.getMapper(UserRepository.class);
User result = repo.get(queryParams);

生成的SQL

SELECT * FROM user 
WHERE 
    id = ? 
    AND password = ?

參數(shù)變化時(shí)的SQL差異

傳入?yún)?shù)生成SQL
只設(shè)置id=1SELECT * FROM user WHERE id = ?
設(shè)置username和passwordSELECT ... WHERE username=? AND password=?
不傳任何參數(shù)SELECT * FROM user(無WHERE條件)

四、高級(jí)技巧:提升動(dòng)態(tài)SQL質(zhì)量

1. 防止空字符串陷阱

<!-- 增加空字符串檢查 -->
<if test="username != null and username != ''">

2. 使用OGNL表達(dá)式增強(qiáng)判斷

<if test="@org.apache.commons.lang3.StringUtils@isNotBlank(email)">
    AND email = #{email}
</if>

3. 復(fù)雜條件組合

<select id="searchUsers">
    SELECT * FROM users
    <where>
        <choose>
            <when test="status != null">
                status = #{status}
            </when>
            <otherwise>
                status = 'ACTIVE'
            </otherwise>
        </choose>
        <if test="name != null">
            AND (first_name LIKE #{name} OR last_name LIKE #{name})
        </if>
    </where>
    ORDER BY
    <foreach item="item" collection="sortBy" separator=",">
        ${item}
    </foreach>
</select>

4. 性能優(yōu)化建議

<!-- 使用<bind>預(yù)先處理值 -->
<bind name="pattern" value="'%' + name + '%'" />
<if test="name != null">
    AND username LIKE #{pattern}
</if>

五、企業(yè)級(jí)應(yīng)用經(jīng)驗(yàn)

典型應(yīng)用場景

  • 動(dòng)態(tài)報(bào)表系統(tǒng):根據(jù)前端選擇的50+字段生成查詢
  • 高級(jí)搜索功能:支持多條件組合篩選
  • 批量操作:使用foreach處理集合參數(shù)
  • 多租戶系統(tǒng):動(dòng)態(tài)添加租戶ID條件

性能監(jiān)控關(guān)鍵指標(biāo)

// 輸出動(dòng)態(tài)SQL
configuration.setLogImpl(StdOutImpl.class);

// 監(jiān)控結(jié)果
DEBUG [main] - ==>  Preparing: SELECT * FROM user WHERE id = ? 
DEBUG [main] - ==> Parameters: 1(Integer)

避坑指南

  • 避免過度動(dòng)態(tài)化:超過10個(gè)條件的查詢建議拆分
  • 注意空格處理:標(biāo)簽內(nèi)換行可能導(dǎo)致SQL語法錯(cuò)誤
  • 慎用${}:優(yōu)先使用#{}防止SQL注入
  • 單元測試覆蓋:至少覆蓋邊界條件組合

在物流系統(tǒng)中應(yīng)用動(dòng)態(tài)SQL的真實(shí)數(shù)據(jù):運(yùn)單查詢接口響應(yīng)時(shí)間從120ms降至45ms,代碼維護(hù)成本降低70%。但切記:動(dòng)態(tài)SQL是利器而非銀彈——當(dāng)邏輯復(fù)雜到難以維護(hù)時(shí),請考慮改用存儲(chǔ)過程或Elasticsearch等專業(yè)方案!

思考題:當(dāng)動(dòng)態(tài)SQL生成的查詢性能突然下降,你會(huì)如何診斷問題?歡迎分享你的排查思路!

到此這篇關(guān)于MyBatis實(shí)戰(zhàn)之動(dòng)態(tài)生成SQL詳解的文章就介紹到這了,更多相關(guān)MyBatis動(dòng)態(tài)SQL內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot 捕捉全局異常 統(tǒng)一返回值的問題

    Spring Boot 捕捉全局異常 統(tǒng)一返回值的問題

    這篇文章主要介紹了Spring Boot 捕捉全局異常 統(tǒng)一返回值,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • MySQL數(shù)據(jù)庫之Purge死鎖問題解析

    MySQL數(shù)據(jù)庫之Purge死鎖問題解析

    這篇文章主要介紹了MySQL數(shù)據(jù)庫之Purge死鎖問題解析的相關(guān)資料,需要的朋友可以參考下
    2017-11-11
  • Java多線程下載網(wǎng)圖的完整案例

    Java多線程下載網(wǎng)圖的完整案例

    這篇文章主要給大家介紹了關(guān)于Java多線程下載網(wǎng)圖的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java中BigDecimal的equals方法和compareTo方法的區(qū)別詳析

    Java中BigDecimal的equals方法和compareTo方法的區(qū)別詳析

    這篇文章主要給大家介紹了關(guān)于Java中BigDecimal的equals方法和compareTo方法區(qū)別的相關(guān)資料,對于BigDecimal的大小比較,用equals方法的話會(huì)不僅會(huì)比較值的大小,還會(huì)比較兩個(gè)對象的精確度,而compareTo方法則不會(huì)比較精確度,只比較數(shù)值的大小,需要的朋友可以參考下
    2023-11-11
  • SpringBoot如何設(shè)置404、500返回統(tǒng)一格式j(luò)son

    SpringBoot如何設(shè)置404、500返回統(tǒng)一格式j(luò)son

    這篇文章主要介紹了SpringBoot如何設(shè)置404、500返回統(tǒng)一格式j(luò)son問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Mybatis批量插入,返回主鍵ID不成功,巨坑記錄

    Mybatis批量插入,返回主鍵ID不成功,巨坑記錄

    這篇文章主要介紹了Mybatis批量插入,返回主鍵ID不成功,巨坑記錄,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java JDK17沒有源碼的問題及解決

    Java JDK17沒有源碼的問題及解決

    這篇文章主要介紹了Java JDK17沒有源碼的問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • System.getProperty(“l(fā)ine.separator“)含義及意義詳解

    System.getProperty(“l(fā)ine.separator“)含義及意義詳解

    這篇文章主要介紹了System.getProperty(“l(fā)ine.separator“)含義,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • SpringBoot?項(xiàng)目打成?jar后加載外部配置文件的操作方法

    SpringBoot?項(xiàng)目打成?jar后加載外部配置文件的操作方法

    這篇文章主要介紹了SpringBoot?項(xiàng)目打成?jar后加載外部配置文件的操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 一篇文章帶你了解JAVA面對對象之繼承與修飾符

    一篇文章帶你了解JAVA面對對象之繼承與修飾符

    這篇文章主要介紹了Java面向?qū)ο缶幊讨惖睦^承,結(jié)合實(shí)例形式較為詳細(xì)的分析了Java面向?qū)ο缶幊填惖母拍睢⒐δ?、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2021-08-08

最新評論

疏附县| 宁陕县| 桐柏县| 新干县| 安顺市| 漳平市| 泰安市| 鞍山市| 金平| 叶城县| 淮安市| 隆安县| 纳雍县| 赞皇县| 梓潼县| 聂拉木县| 澄城县| 濉溪县| 桑日县| 通州市| 大渡口区| 利川市| 清苑县| 瓮安县| 平度市| 颍上县| 赞皇县| 岑溪市| 福建省| 高邮市| 南郑县| 藁城市| 上杭县| 澎湖县| 夏邑县| 黑山县| 项城市| 称多县| 耒阳市| 探索| 江门市|