MyBatis動態SQL實戰:告別硬編碼,擁抱智能SQL生成

MyBatis動態SQL實戰:告別硬編碼,擁抱智能SQL生成

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

一、為什么需要動態SQL?

傳統SQL拼接的痛點

// 傳統方式需要手動拼接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注入風險!且代碼冗長難維護

動態SQL的核心價值

  1. 消除重復代碼:相同業務邏輯不再需要重復編寫
  2. 防止SQL注入:自動使用預編譯參數
  3. 提升可讀性:SQL與Java邏輯解耦
  4. 降低出錯率:避免手動拼接錯誤

二、動態SQL核心標簽解析

1. <if> 標簽:條件分支處理

業務場景:根據傳入參數動態添加查詢條件

<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>

執行原理
在這里插入圖片描述

2. <where> 標簽:智能WHERE處理

自動處理

  • 條件前多余的AND/OR
  • 當所有條件都不滿足時,移除WHERE關鍵字

錯誤示例

<!-- 當所有if都不滿足時,SQL會變成: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. 其他核心標簽

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

三、最佳實踐:用戶查詢案例

Java調用代碼

// 創建參數對象
User queryParams = new User();
queryParams.setId(1);
queryParams.setPassword("securePass123");// 執行動態查詢
UserRepository repo = sqlSession.getMapper(UserRepository.class);
User result = repo.get(queryParams);

生成的SQL

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

參數變化時的SQL差異

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

四、高級技巧:提升動態SQL質量

1. 防止空字符串陷阱

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

2. 使用OGNL表達式增強判斷

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

3. 復雜條件組合

<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. 性能優化建議

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

五、企業級應用經驗

典型應用場景

  1. 動態報表系統:根據前端選擇的50+字段生成查詢
  2. 高級搜索功能:支持多條件組合篩選
  3. 批量操作:使用foreach處理集合參數
  4. 多租戶系統:動態添加租戶ID條件

性能監控關鍵指標

// 輸出動態SQL
configuration.setLogImpl(StdOutImpl.class);// 監控結果
DEBUG [main] - ==>  Preparing: SELECT * FROM user WHERE id = ? 
DEBUG [main] - ==> Parameters: 1(Integer)

避坑指南

  1. 避免過度動態化:超過10個條件的查詢建議拆分
  2. 注意空格處理:標簽內換行可能導致SQL語法錯誤
  3. 慎用${}:優先使用#{}防止SQL注入
  4. 單元測試覆蓋:至少覆蓋邊界條件組合

在物流系統中應用動態SQL的真實數據:運單查詢接口響應時間從120ms降至45ms,代碼維護成本降低70%。但切記:動態SQL是利器而非銀彈——當邏輯復雜到難以維護時,請考慮改用存儲過程或Elasticsearch等專業方案!

思考題:當動態SQL生成的查詢性能突然下降,你會如何診斷問題?歡迎分享你的排查思路!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90174.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90174.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90174.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Web前端開發:JavaScript遍歷方法詳解與對比

1. 傳統 for 循環const arr [10, 20, 30]; for (let i 0; i < arr.length; i) {console.log(索引 ${i}: 值 ${arr[i]}); } // 輸出&#xff1a; // 索引 0: 值 10 // 索引 1: 值 20 // 索引 2: 值 30特點&#xff1a;最基礎的循環&#xff0c;可通過索引精準控制適用場景&…

Python 爬蟲(一):爬蟲偽裝

目錄 1 簡介2 偽裝策略 2.1 Request Headers 問題2.2 IP 限制問題 3 總結 1 簡介 對于一些有一定規模或盈利性質比較強的網站&#xff0c;幾乎都會做一些防爬措施&#xff0c;防爬措施一般來說有兩種&#xff1a;一種是做身份驗證&#xff0c;直接把蟲子擋在了門口&#xff…

TODAY()-WEEKDAY(TODAY(),2)+1

這個Excel公式 TODAY()-WEEKDAY(TODAY(),2)1 用于計算 當前周的周一日期。下面詳細解釋它的邏輯和用法&#xff1a;公式解析TODAY()返回當前日期&#xff08;例如今天是2023年12月20日&#xff0c;則 TODAY() 2023/12/20&#xff09;。WEEKDAY(TODAY(), 2)計算當前日期是星期幾…

Fast Frequency Estimation Algorithm by Least Squares Phase Unwrapping

I. 引言 單個含噪正弦信號的頻率估計是一個研究已久的問題&#xff0c;并有多種應用[1]。在高斯白噪聲假設下&#xff0c;最大似然(ML)頻率估計器是Rife和Boorstyn [2]中提出的周期圖估計器&#xff0c;其中傅里葉變換用于搜索周期圖的最大值。周期圖估計器被廣泛認為是單頻估計…

C語言常見的預定符號常量

C語言常見的預定符號常量C 語言提供了豐富的預定義符號常量&#xff0c;分布在不同頭文件中&#xff0c;用于獲取編譯信息、數值范圍、浮點特性等關鍵信息。以下是常見預定義符號常量的分類總結&#xff1a;一、預定義宏&#xff08;編譯時信息&#xff09;由編譯器自動定義&am…

【2025】使用vue構建一個漂亮的天氣卡片

1. 核心框架&#xff1a;Vue Vue 以其輕量、易用、響應式數據綁定的特點&#xff0c;非常適合快速構建這類小型界面組件。即使是直接通過 CDN 引入&#xff0c;也能高效開發&#xff0c;降低項目復雜度&#xff0c;無需搭建完整工程化環境 。 2. 網絡請求&#xff1a;Axios 用于…

Ruby 命令行選項詳解

Ruby 命令行選項詳解 引言 Ruby 是一種廣泛使用的編程語言,它以其簡潔、優雅和強大的功能而聞名。在 Ruby 的使用過程中,命令行界面(CLI)提供了豐富的選項,可以幫助開發者更高效地與 Ruby 環境交互。本文將詳細解析 Ruby 命令行選項,旨在幫助開發者更好地利用這些工具。…

NLP復習

1.文本預處理 分詞,詞性標注,命名實體識別 1.1分詞:jieba jieba.lcut(content,cut_alltrue) 全模式 jieba.lcut(content,cut_allfalse) 精確模式 jieba.lcut_for_search(content) 搜索引擎模式 lcut和cut的區別:cut返回的是一個生成器Generator,lcut返回的是列表 生成器調…

WEB :實戰演練——從零實現一個交互輪播圖(附源碼)

文章目錄 一、輪播圖整體功能規劃二、HTML結構深度解析三、CSS樣式實現細節1. 定位系統詳解2. 顯示/隱藏機制3. 按鈕交互效果實現4. 純CSS箭頭實現5. 指示器&#xff1a;當前位置可視化 四、JavaScript邏輯深入解析1. 核心變量與DOM獲取2. 圖片切換函數&#xff08;核心邏輯&am…

MCP 協議詳細分析一 initialize ping tools/list tools/call

MCP 協議詳細分析一 &#xff08;initialize ping tools/list tools/call) 本節基于 實現一個 java 的mcp client 調用的 一個python 的mcp server 的日志&#xff0c;完整展示一次典型的 MCP Java SDK 通信流程、工具調用、通知機制與日志記錄&#xff0c;僅包含 echo-simple…

SLAM學習資料記錄

ORB_SLAM2 創建自己的數據集&#xff08;還未使用&#xff09; 【SLAM實戰篇】Ubuntu 20.04版本&#xff08;OpenCV版本4.5.3&#xff09;對于ORB-SLAM2安裝運行&#xff0c;代碼編譯&#xff0c;自己的數據集構造_ubuntu20.04 安裝運行orb_slam2算法-CSDN博客 卡爾曼濾波數據…

用Phi-3 Mini微調實現英文到尤達語翻譯

用Phi-3 Mini微調實現英文到尤達語翻譯 引言 本文將帶你快速上手大模型微調實踐——以微軟的Phi-3 Mini 4K Instruct模型為例&#xff0c;教你如何將其微調為一個能把英文翻譯成"尤達語"&#xff08;《星球大戰》中尤達大師的獨特說話風格&#xff09;的模型。這是一…

AI助力,輕松實現人聲分離伴奏提取

親愛的小伙伴們&#xff01;前段時間&#xff0c;有一位同事家的可愛小孩參加了一場英語演講比賽。同事找到我&#xff0c;希望我能幫個忙&#xff0c;把講視頻中的人聲去掉&#xff0c;只提取出其中相應的伴奏。今天&#xff0c;我就來和大家分享一下究竟如何實現從 MP4 視頻中…

第1章第2章筆記

OSI參考模型---開放式系統互聯模型---OSI/RM ISO--->國際標準化組織&#xff1b;特點&#xff1a;先有模型&#xff0c;在又協議。 OSI七層參考模型&#xff1a;應用層 --- 提供網絡服務&#xff1b;自然語言-->編碼表示層 --- 對數據的處理&#xff1b;格式化&#xff0…

圖的BFS和DFS

一&#xff0c;圖的遍歷邏輯1.之前我們學了圖的存儲&#xff0c;可以鄰接表存和鄰接矩陣存。現在我們要學習圖的遍歷操作和樹類似可以分為深度遍歷和廣度遍歷&#xff0c;而深度遍歷也是用遞歸實現&#xff0c;廣度遍歷是用隊列實現2.深度遍歷(DFS)a.確定起點b.找到一條邊按順時…

WWDC 25 給自定義 SwiftUI 視圖穿上“玻璃外衣”:最新 Liquid Glass 皮膚詳解

引子 各位 iOS 足球體育健兒們&#xff0c;且聽我一言&#xff01;想當年在《少林足球》里&#xff0c;阿星一句“做人如果沒夢想&#xff0c;那跟咸魚有什么分別啊&#xff1f;”點燃了多少人的江湖夢。 如今在 SwiftUI 江湖里&#xff0c;Apple 于 WWDC 25 推出的 Liquid Gl…

Day01_C++

01.思維導圖02.方法一&#xff1a;#include <iostream> #include <cstring> #include <iostream> using namespace std; class mystring { private:char* buf;int len;public:mystring(const char* str);void copy(const char* ptr);void copy(mystring ptr)…

C語言學習(days09)

二維數組的定義與特性二維數組的聲明格式為&#xff1a;類型說明符 數組名[表達式1][表達式2];[下標1]表示行索引&#xff0c;[下標2]表示列索引。二維數組可視為由多個一維數組組成&#xff0c;a[0]表示第0行的首地址&#xff08;即一維數組地址&#xff09;a[0][0]表示第0的第…

WIFI路由器長期不重啟,手機連接時提示無IP分配

今天在公司&#xff0c;突然發現手機連不上公司WIFI。每次鏈接&#xff0c;提示無IP分析。我以為是我手機出問題了&#xff0c;想復位一下。后來一想萬一復位還是不靈&#xff0c;怎么辦&#xff1f;同事認為是路由器沒有重啟的原因。于是找到路由器&#xff0c;重啟&#xff0…

【前沿技術動態】【AI總結】RustFS:從 0 到 1 打造下一代分布式對象存儲

目錄1 引言&#xff1a;為什么我們又需要一個新的對象存儲2 RustFS 全景速覽3 技術架構深度拆解3.1 整體拓撲3.2 關鍵數據結構&#xff08;rust 偽代碼&#xff09;3.3 讀寫路徑&#xff08;寫放大 < 1.1&#xff09;4 核心源碼導讀4.1 關鍵函數跟蹤4.2 一段最小可復現示例5…