首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

MyBatis 動態 SQL 完全指南:if/choose/trim/where/set/foreach 六大核心標籤深度解析

     編輯:關於SqlServer

為什麼需要動態 SQL?

傳統 JDBC 拼接 SQL 字串痛苦不堪:空格遺漏、逗號殘留、條件組合爆炸。MyBatis 基於 OGNL 表達式 的動態 SQL 標籤,將條件構建邏輯直接寫在映射檔中,徹底解決此痛點。

六大核心標籤詳細解析

1. <if>:單一條件判斷


<select id="dynamicIfTest" resultType="Blog">
  SELECT * FROM t_blog WHERE 1=1
  <if test="title != null">
    AND title = #{title}
  </if>
  <if test="content != null">
    AND content = #{content}
  </if>
  <if test="owner != null">
    AND owner = #{owner}
  </if>
</select>

提供參數時自動拼接對應條件,缺省則忽略。

2. <choose>/<when>/<otherwise>:互斥條件分支(類 switch-case)


<select id="dynamicChooseTest" resultType="Blog">
  SELECT * FROM t_blog WHERE 1=1
  <choose>
    <when test="title != null"> AND title = #{title} </when>
    <when test="content != null"> AND content = #{content} </when>
    <otherwise> AND owner = 'owner1' </otherwise>
  </choose>
</select>

按順序評估,首個符合的 when 生效,其餘忽略。全不符合時走 otherwise。

3. <where>:智慧 WHERE 子句處理


<select id="dynamicWhereTest" resultType="Blog">
  SELECT * FROM t_blog
  <where>
    <if test="title != null"> title = #{title} </if>
    <if test="content != null"> AND content = #{content} </if>
    <if test="owner != null"> AND owner = #{owner} </if>
  </where>
</select>

智慧行為:

  • 自動插入 WHERE 關鍵字
  • 首個條件若為 AND/OR 開頭,自動移除
  • 所有條件不滿足時,不輸出 WHERE(查全表)
  • 自動處理空格

4. <trim>:通用前後綴處理(可替代 where)


<select id="dynamicTrimTest" resultType="Blog">
  SELECT * FROM t_blog
  <trim prefix="WHERE" prefixOverrides="AND |OR">
    <if test="title != null"> title = #{title} </if>
    <if test="content != null"> AND content = #{content} </if>
    <if test="owner != null"> OR owner = #{owner} </if>
  </trim>
</select>

屬性對應:

屬性功能
prefix內容前加前綴
suffix內容後加後綴
prefixOverrides移除內容開頭的指定字串
suffixOverrides移除內容結尾的指定字串

5. <set>:UPDATE 子句智慧處理


<update id="dynamicSetTest" parameterType="Blog">
  UPDATE t_blog
  <set>
    <if test="title != null"> title = #{title}, </if>
    <if test="content != null"> content = #{content}, </if>
    <if test="owner != null"> owner = #{owner} </if>
  </set>
  WHERE id = #{id}
</update>

智慧行為:自動輸出 SET,移除結尾逗號。注意:若所有條件均不滿足(set 內容為空),會拋出異常。

6. <foreach>:集合迭代構建 IN 條件(最強大、最易錯)


<select id="dynamicForeachTest" resultType="Blog">
  SELECT * FROM t_blog WHERE id IN
  <foreach collection="list" item="item" index="index" 
       open="(" separator="," close=")">
    #{item}
  </foreach>
</select>

屬性詳解:

屬性說明
collection關鍵,三種情況值不同(見下表)
item迭代元素別名
index索引別名(List 為索引,Map 為鍵)
open/separator/close包圍字串、分隔符、結尾字串

collection 三種傳參場景對照表

傳參類型Java 介面collection 值
單參數 ListList<Blog> dynamicForeachTest(List<Integer> ids)list
單參數 ArrayList<Blog> dynamicForeach2Test(int[] ids)array
多參數/MapList<Blog> dynamicForeach3Test(Map<String,Object> params)Map 中的 Key(如 ids)

Map 傳參完整範例


<select id="dynamicForeach3Test" resultType="Blog">
  SELECT * FROM t_blog 
  WHERE title LIKE "%"#{title}"%" 
  AND id IN
  <foreach collection="ids" item="item" open="(" separator="," close=")">
    #{item}
  </foreach>
</select>

-- Java 調用
Map<String, Object> params = new HashMap<>();
params.put("ids", Arrays.asList(1,2,3,6,7,9));
params.put("title", "中國");
blogMapper.dynamicForeach3Test(params);

最佳實踐與避坑指南

  1. 優先使用 <where> 和 <set>,減少手動處理 AND/OR/逗號邏輯
  2. foreach 的 collection 必須正確對應傳參結構,錯誤會導致「BindingException: Parameter 'xxx' not found」
  3. 複雜條件組合用 <choose> 替代多層巢狀 <if>
  4. OGNL 表達式支援方法呼叫:test="@util@isNotEmpty(title)"
  5. 動態 SQL 仍需防注入:#{param} 使用預編譯,${param} 直接拼接(僅用於表名/欄位名等不可參數化場景)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved