MyBatis—動態 SQL

MyBatis—動態 SQL

一、動態 SQL 的核心作用

動態 SQL 主要解決以下問題:

  1. 靈活性:根據不同的輸入參數生成不同的 SQL 語句(如條件查詢、批量操作)。

  2. 可維護性:減少重復代碼,通過標簽化邏輯提高 SQL 可讀性。

  3. 安全性:自動處理參數綁定,防止 SQL 注入。

二、常用動態 SQL 標簽

MyBatis 提供了以下標簽來實現動態 SQL:

1. <if>:條件判斷
  • 根據參數值是否滿足條件,決定是否包含 SQL 片段。
  • 示例:
<select id="findUser" resultType="User">SELECT * FROM users<where><if test="name != null and name != ''">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></where>
</select>
  • 說明:如果 nameage 為空,則對應的條件不會被包含。
2. <choose>/<when>/<otherwise>:多條件選擇
  • 類似于 Java 的 switch-case,按順序判斷條件。

  • 示例:

    <select id="findUserByCondition" resultType="User">SELECT * FROM users<where><choose><when test="name != null">AND name = #{name}</when><when test="email != null">AND email = #{email}</when><otherwise>AND status = 'active'</otherwise></choose></where>
    </select>
    
  • 說明:按順序判斷 nameemail,若都不滿足則執行默認條件。

3. <where>:智能處理 WHERE 子句
  • 自動去除多余的 ANDOR,并自動添加 WHERE 關鍵字。

  • 示例:

    <select id="findUser" resultType="User">SELECT * FROM users<where><if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></where>
    </select>
    
    • 結果:若 nameage 都為空,則生成 SELECT * FROM users(無 WHERE 子句);若 name 不為空,則生成 WHERE name = ?
4. <set>:動態更新字段
  • 用于 UPDATE 語句,自動去除末尾逗號。

  • 示例:

    <update id="updateUser">UPDATE users<set><if test="name != null">name = #{name},</if><if test="email != null">email = #{email},</if></set>WHERE id = #{id}
    </update>
    
    • 結果:若 nameemail 都不為空,生成 SET name = ?, email = ?;若只有一個字段不為空,自動去除末尾逗號。
5. <foreach>:遍歷集合
  • 用于批量操作(如 IN 子句、批量插入)。

  • 示例:

    <select id="findUsersByIds" resultType="User">SELECT * FROM usersWHERE id IN<foreach item="id" collection="list" open="(" separator="," close=")">#{id}</foreach>
    </select>
    
    • 結果:若傳入的 list[1, 2, 3],生成 WHERE id IN (1, 2, 3)
6. <trim>:靈活拼接 SQL
  • 手動控制 SQL 片段的前綴和后綴,常用于復雜邏輯。

  • 示例:

    <trim prefix="WHERE" prefixOverrides="AND |OR "><if test="name != null">AND name = #{name}</if>
    </trim>
    
    • 說明:若 name 為空,則不生成 WHERE;若 name 不為空,生成 WHERE name = ?

三、動態 SQL 的實現原理

  1. XML 解析:MyBatis 啟動時加載 Mapper XML 文件,解析動態 SQL 標簽。
  2. SQL 拼接:運行時根據傳入參數動態生成 SQL 片段。
  3. 參數綁定:使用 #{} 綁定參數,防止 SQL 注入。
  4. 預編譯:最終生成的 SQL 被發送給數據庫驅動,創建 PreparedStatement

四、動態 SQL 的應用場景

  1. 條件查詢:根據用戶輸入動態過濾條件。
  2. 批量操作:批量插入、更新、刪除。
  3. 多表關聯:根據業務需求動態關聯不同表。
  4. 復雜業務邏輯:如動態排序、分頁等。

五、最佳實踐

  1. 避免復雜嵌套:過多嵌套會降低可讀性,建議拆分邏輯。
  2. 合理使用 <where><set>:簡化 SQL 片段。
  3. 測試動態 SQL:通過日志查看生成的 SQL,確保邏輯正確。
  4. 參數校驗:在業務層校驗參數,避免無效條件。

六、示例:綜合使用動態 SQL(實戰)

比如我們已經寫完了controller層,entity層,mapper層,service層等Impl。

動態SQL實現:修改mapper層:(注釋掉SQL注解)

@Mapper
public interface UsersMapper {@Select("insert into users(account,password,uname,gender,age,phone,email,address,avatar,regtime,uflag) values(#{account},#{password},#{uname},#{gender},#{age},#{phone},#{email},#{address},#{avatar},#{regtime},#{uflag})")void addUser(Users users);@Select("select * from users where account=#{account}")Users getUserByAccount(String account);//    @Select("select * from users where uflag = #{uflag} order by regtime desc")List<Users> queryUsersByUflag(Users users);//根據id查詢用戶@Select("select * from users where account = #{id}")Users queryUsersById(String id);//審核通過
//    @Update("update users set uflag = #{uflag} where account = #{account}")void updateUser(Users users);//刪除家長@Delete("delete from users where account = #{id}")void delUsers(String id);
}

這些SQL注解我們寫進resources/mapper/UsersMapper.xml這里。

例如:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bkty.turtorsystem.mapper.UsersMapper"><!--根據動態的條件查詢用戶--><select id="queryUsersByUflag"  resultType="Users"parameterType="Users">select * from users<where><if test="uflag != null and uflag != ''">uflag = #{uflag}</if><if test="account != null and account != ''">and account = #{account}</if><if test="uname != null and uname != ''">and uname = #{uname}</if><if test="password != null and password != ''">and password = #{password}</if><if test="email != null and email != ''">email = #{email}</if><if test="phone != null and phone != ''">and phone like concat('%',#{phone},'%')</if><if test="gender != null and gender != ''">and gender = #{gender}</if><if test="age != null and age != ''">and age = #{age}</if><if test="address != null and address != ''">address = #{address}</if><if test="condition != null and condition != ''">${condition}</if></where>order by regtime desc</select><update id="updateUser" parameterType="Users">update users<set><if test="account != null and account != ''">account = #{account},</if><if test="password != null and password != ''">password = #{password},</if><if test="uname != null and uname != ''">uname = #{uname},</if><if test="gender != null and gender != ''">gender = #{gender},</if><if test="age != null and age != ''">age = #{age},</if><if test="phone != null and phone != ''">phone = #{phone},</if><if test="email != null and email != ''">email = #{email},</if><if test="address != null and address != ''">address = #{address},</if><if test="avatar != null and avatar != ''">avatar = #{avatar},</if><if test="regtime != null and regtime != ''">regtime = #{regtime},</if><if test="uflag != null and uflag != ''">uflag =#{uflag},</if></set>where account = #{account}</update>
</mapper>
<mapper namespace="com.bkty.turtorsystem.mapper.UsersMapper">

這個namespace=指向我的mapper,相當于注解SQL,把注解改成了xml。

1. 查詢語句:queryUsersByUflag

<select id="queryUsersByUflag" resultType="Users" parameterType="Users">select * from users<where><if test="uflag != null and uflag != ''">uflag = #{uflag}</if><if test="account != null and account != ''">and account = #{account}</if><!-- 其他字段的 <if> 條件 --><if test="condition != null and condition != ''">${condition}</if></where>order by regtime desc
</select>
功能說明
  • 作用:根據傳入的 Users 對象中的字段動態生成 SQL 查詢條件,查詢 users 表中的記錄。
  • 動態條件:
    • 使用 <where> 標簽包裹所有條件,MyBatis 會自動處理 ANDOR 的冗余問題(例如,如果第一個條件不成立,WHERE 關鍵字不會被輸出)。
    • 每個 <if> 標簽檢查字段是否非空,若非空則添加對應的查詢條件。
    • 特殊字段 condition 使用 ${condition} 直接拼接 SQL(需注意 SQL 注入風險)。
關鍵點
  1. 字段條件:
    • 所有字段(如 uflag, account, uname 等)都通過 <if> 動態判斷是否添加到查詢條件中。
    • 注意:第一個條件(uflag)沒有加 AND,但 <where> 標簽會自動處理這種情況,避免語法錯誤。
  2. condition 字段:
    • 使用 ${condition} 直接拼接原始 SQL 片段(例如 1=1status='active')。
    • 風險${} 不會進行參數綁定,存在 SQL 注入風險,需確保傳入值的安全性。
  3. 排序:
    • 固定按 regtime 降序排列。
示例

假設傳入的 Users 對象包含 uflag="1"account="test123",生成的 SQL 為:

SELECT * FROM users 
WHERE uflag = '1' AND account = 'test123' 
ORDER BY regtime DESC;

2. 更新語句:updateUser

<update id="updateUser" parameterType="Users">update users<set><if test="account != null and account != ''">account = #{account},</if><!-- 其他字段的 <if> 條件 --><if test="uflag != null and uflag != ''">uflag =#{uflag},</if></set>where account = #{account}
</update>
功能說明
  • 作用:根據傳入的 Users 對象中的字段動態更新 users 表中的記錄。
  • 動態更新字段:
    • 使用 <set> 標簽包裹所有字段更新邏輯,MyBatis 會自動去除末尾多余的逗號。
    • 每個 <if> 標簽判斷字段是否非空,若非空則更新對應字段。
  • 更新條件:
    • 使用 account = #{account} 作為更新條件(需確保 account 是唯一標識字段)。
關鍵點
  1. 字段更新:
    • 所有字段(如 account, password, uname 等)都通過 <if> 動態判斷是否更新。
    • 注意:每個字段條件后都有逗號 ,,但 <set> 會自動去除最后一個字段的逗號。
  2. 更新條件:
    • 使用 account = #{account} 作為更新條件,需確保 account 是唯一值(否則可能更新多條記錄)。
  3. 潛在問題:
    • 如果 account 不唯一,可能會導致意外更新多條記錄。
    • 更推薦使用主鍵(如 id)作為更新條件。
示例

假設傳入的 Users 對象包含 account="test123"uname="NewName",生成的 SQL 為:

UPDATE users 
SET account = 'test123', uname = 'NewName' 
WHERE account = 'test123';

七、總結

MyBatis 的動態 SQL 通過標簽化邏輯,解決了傳統 SQL 硬編碼的問題,使代碼更簡潔、安全且靈活。合理使用 <if><where><foreach> 等標簽,可以大幅提升開發效率和代碼質量。

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

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

相關文章

Python機器學習筆記(二十五、算法鏈與管道)

對于許多機器學習算法,特定數據表示非常重要。首先對數據進行縮放,然后手動合并特征,再利用無監督機器學習來學習特征。因此,大多數機器學習應用不僅需要應用單個算法,而且還需要將許多不同的處理步驟和機器學習模型鏈接在一起。Pipeline類可以用來簡化構建變換和模型鏈的…

YOLOv3深度解析:多尺度特征融合與實時檢測的里程碑

一、YOLOv3的誕生&#xff1a;繼承與突破的起點 YOLOv3作為YOLO系列的第三代算法&#xff0c;于2018年由Joseph Redmon等人提出。它在YOLOv2的基礎上&#xff0c;針對小目標檢測精度低、多類別標簽預測受限等問題進行了系統性改進。通過引入多尺度特征圖檢測、殘差網絡架構和獨…

已解決(親測有效!):安裝部署Docker Deskpot之后啟動出現Docker Engine Stopped!

文章目錄 已解決&#xff1a;安裝部署Docker Deskpot之后啟動出現Docker Engine Stopped&#xff01;個人環境介紹自己的解決問題思路&#xff08;詳細過程附截圖&#xff09;1.打開控制面板2.點擊程序和功能3.點擊啟動或關閉windows功能4.Hyper-V5.右鍵菜單欄的windows圖標點擊…

PCIE接收端檢測機制分析

PCIE接收端檢測機制分析 1、PCIE的接收端檢測機制 接收器檢測電路作為發射器的一部分實現&#xff0c;必須正確檢測是否存在與ZRX-DC參數&#xff08;40Ω-60Ω&#xff09;隱含的直流阻抗等效的負載阻抗。 接收器檢測序列的推薦行為如下&#xff1a; ?初始狀態?&#xff…

[模型部署] 3. 性能優化

&#x1f44b; 你好&#xff01;這里有實用干貨與深度分享?? 若有幫助&#xff0c;歡迎&#xff1a;? &#x1f44d; 點贊 | ? 收藏 | &#x1f4ac; 評論 | ? 關注 &#xff0c;解鎖更多精彩&#xff01;? &#x1f4c1; 收藏專欄即可第一時間獲取最新推送&#x1f514;…

InternVL3: 利用AI處理文本、圖像、視頻、OCR和數據分析

InternVL3推動了視覺-語言理解、推理和感知的邊界。 在其前身InternVL 2.5的基礎上,這個新版本引入了工具使用、GUI代理操作、3D視覺和工業圖像分析方面的突破性能力。 讓我們來分析一下是什么讓InternVL3成為游戲規則的改變者 — 以及今天你如何開始嘗試使用它。 InternVL…

鴻蒙 ArkUI - ArkTS 組件 官方 UI組件 合集

ArkUI 組件速查表 鴻蒙應用開發頁面上需要實現的 UI 功能組件如果在這 100 多個組件里都找不到&#xff0c;那就需要組合造輪子了 使用技巧&#xff1a;先判斷需要實現的組件大方向&#xff0c;比如“選擇”、“文本”、“信息”等&#xff0c;或者是某種形狀比如“塊”、“圖…

HTTP GET報文解讀

考慮當瀏覽器發送一個HTTP GET報文時&#xff0c;通過Wireshark 俘獲到下列ASCII字符串&#xff1a; GET /cs453/index.html HTTP/1.1 Host: gaia.cs.umass.edu User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax) Acc…

【Linux網絡】數據鏈路層

數據鏈路層 用于兩個設備&#xff08;同一種數據鏈路節點&#xff09;之間進行傳遞。 認識以太網 “以太網” 不是一種具體的網絡&#xff0c;而是一種技術標準&#xff1b;既包含了數據鏈路層的內容&#xff0c;也包含了一些物理層的內容。例如&#xff1a;規定了網絡拓撲結…

【打破信息差】萌新認識與入門算法競賽

閱前須知 XCPC萌新互助進步群2??&#xff1a;174495261 博客主頁&#xff1a;resot (關注resot謝謝喵) 針對具體問題&#xff0c;應當進行具體分析&#xff1b;并無放之四海而皆準的方法可適用于所有人。本人尊重并支持每位學習者對最佳學習路徑的自主選擇。本篇所列訓練方…

logrotate按文件大小進行日志切割

? 編寫logrotate文件&#xff0c;進行自定義切割方式 adminip-127-0-0-1:/data/test$ cat /etc/logrotate.d/test /data/test/test.log {size 1024M #文件達到1G就切割rotate 100 #保留100個文件compressdelaycompressmissingoknotifemptycopytruncate #這個情況服務不用…

2025認證杯二階段C題完整論文講解+多模型對比

基于延遲估計與多模型預測的化工生產過程不合格事件預警方法研究 摘要 化工生產過程中&#xff0c;污染物濃度如SO?和H?S對生產過程的控制至關重要。本文旨在通過數據分析與模型預測&#xff0c;提出一種基于延遲估計與特征提取的多模型預測方法&#xff0c;優化閾值設置&a…

前端精度問題全解析:用“挖掘機”快速“填平精度坑”的完美解決方案

寫在前面 “為什么我的計算在 React Native 中總是出現奇怪的精度問題?” —— 這可能是許多開發者在作前端程序猿的朋友們都會遇到的第一個頭疼問題。本文將深入探討前端精度問題的根源,我將以RN為例,并提供一系列實用解決方案,讓你的應用告別計算誤差。 一、精度問題的…

2024 睿抗機器人開發者大賽CAIP-編程技能賽-本科組(國賽) 解題報告 | 珂學家

前言 題解 2024 睿抗機器人開發者大賽CAIP-編程技能賽-本科組(國賽)。 國賽比省賽難一些&#xff0c;做得汗流浹背&#xff0c;T_T. RC-u1 大家一起查作弊 分值: 15分 這題真的太有意思&#xff0c;看看描述 在今年的睿抗比賽上&#xff0c;有同學的提交代碼如下&#xff1…

hghac和hgproxy版本升級相關操作和注意事項

文章目錄 環境文檔用途詳細信息 環境 系統平臺&#xff1a;N/A 版本&#xff1a;4.5.6,4.5.7,4.5.8 文檔用途 本文檔用于高可用集群環境中hghac組件和hgproxy組件替換和升級操作 詳細信息 1.關閉服務 所有數據節點都執行 1、關閉hgproxy服務 [roothgdb01 tools]# system…

userfaultfd內核線程D狀態問題排查

問題現象 運維反應機器上出現了很多D狀態進程&#xff0c;也kill不掉,然后將現場保留下來進行排查。 排查過程 都是內核線程&#xff0c;先看下內核棧D在哪了&#xff0c;發現D在了userfaultfd的pagefault流程。 uffd知識補充 uffd探究 uffd在firecracker與e2b的架構下使…

深入解析:構建高性能異步HTTP客戶端的工程實踐

一、架構設計原理與核心優勢 HTTP/2多路復用技術的本質是通過單一的TCP連接并行處理多個請求/響應流&#xff0c;突破了HTTP/1.1的隊頭阻塞限制。在異步編程模型下&#xff0c;這種特性與事件循環機制完美結合&#xff0c;形成了高性能網絡通信的黃金組合。相較于傳統同步客戶…

根據臺賬批量制作個人表

1. 前期材料準備 1&#xff09;要有 人員總的信息臺賬 2&#xff09;要有 個人明白卡模板 2. 開始操作 1&#xff09;打開 人員總的信息臺賬&#xff0c;選擇所需要的數據模塊&#xff1b; 2&#xff09;點擊插入&#xff0c;選擇數據透視表&#xff0c;按流程操作&…

《AI大模型應知應會100篇》第65篇:基于大模型的文檔問答系統實現

第65篇&#xff1a;基于大模型的文檔問答系統實現 &#x1f4da; 摘要&#xff1a;本文詳解如何構建一個基于大語言模型&#xff08;LLM&#xff09;的文檔問答系統&#xff0c;支持用戶上傳 PDF 或 Word 文檔&#xff0c;并根據其內容進行智能問答。從文檔解析、向量化、存儲到…

RTK哪個品牌好?2025年RTK主流品牌深度解析

在測繪領域&#xff0c;RTK 技術的發展日新月異&#xff0c;選擇一款性能卓越、穩定可靠的 RTK 設備至關重要。2025 年&#xff0c;市場上涌現出眾多優秀品牌&#xff0c;本文將深入解析幾大主流品牌的核心競爭力。 華測導航&#xff08;CHCNAV&#xff09;&#xff1a;技術創…