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

一文詳解MyBatis中動態(tài)SQL的封裝原理與常用標(biāo)簽實(shí)戰(zhàn)應(yīng)用

 更新時間:2026年04月08日 09:02:15   作者:身如柳絮隨風(fēng)揚(yáng)  
這篇文章主要為大家詳細(xì)介紹了MyBatis中動態(tài)SQL的核心技術(shù)與及常用標(biāo)簽的應(yīng)用,同時提供了最佳實(shí)踐和常見問題解決方案,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

告別繁瑣的SQL拼接,讓動態(tài)查詢像搭積木一樣簡單

一、為什么需要動態(tài)SQL?

在實(shí)際開發(fā)中,我們經(jīng)常會遇到需要根據(jù)不同的條件拼接SQL語句的場景。傳統(tǒng)的做法是使用Java代碼進(jìn)行字符串拼接,但這種方式不僅代碼冗余、易出錯,還存在SQL注入的風(fēng)險。MyBatis提供的動態(tài)SQL機(jī)制,允許我們在XML映射文件中使用標(biāo)簽來構(gòu)建靈活的SQL語句,讓代碼更清晰、更安全。

核心優(yōu)勢:

  • 無需手動處理多余的空格、AND/OR、逗號分隔符
  • 基于OGNL表達(dá)式,與Java對象無縫集成
  • 提升可維護(hù)性,SQL結(jié)構(gòu)一目了然

二、動態(tài)SQL的執(zhí)行流程

MyBatis在解析動態(tài)SQL時,會根據(jù)傳入的參數(shù)動態(tài)生成最終的SQL語句。下圖展示了從XML到預(yù)編譯SQL的完整過程:

三、常用動態(tài)SQL標(biāo)簽詳解

1.<if>– 條件判斷

最簡單的條件標(biāo)簽,當(dāng)條件滿足時拼接SQL片段。

語法:

<if test="條件表達(dá)式">
    SQL片段
</if>

示例: 根據(jù)姓名和年齡動態(tài)查詢用戶

<select id="findUsers" resultType="User">
    SELECT * FROM user WHERE 1=1
    <if test="name != null and name != ''">
        AND name = #{name}
    </if>
    <if test="age != null and age > 0">
        AND age = #{age}
    </if>
</select>

注意: WHERE 1=1 是為了防止所有條件都不滿足時出現(xiàn)語法錯誤。更好的替代方案是使用 <where> 標(biāo)簽。

2.<where>– 智能處理查詢條件

自動處理AND/OR關(guān)鍵字,并去除多余的連接詞。

示例: 重構(gòu)上面的查詢

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

當(dāng) name 有值而 agenull 時,生成的SQL為:

  • SELECT * FROM user WHERE name = ?
  • <where> 標(biāo)簽會自動去掉開頭的 AND。

3.<set>– 動態(tài)更新字段

<update> 語句中智能處理逗號分隔符。

示例: 動態(tài)更新用戶信息

<update id="updateUser">
    UPDATE user
    <set>
        <if test="name != null">name = #{name},</if>
        <if test="age != null">age = #{age},</if>
        <if test="email != null">email = #{email},</if>
    </set>
    WHERE id = #{id}
</update>

<set> 會自動去掉末尾多余的逗號,并保證至少有一個字段被更新。

4.<foreach>– 遍歷集合/數(shù)組

常用于 IN 查詢、批量插入、批量刪除。

屬性說明:

屬性作用
collection要遍歷的集合/數(shù)組名稱
item每次迭代的當(dāng)前元素別名
index當(dāng)前元素的索引(或map的key)
open遍歷開始拼接的字符串
close遍歷結(jié)束拼接的字符串
separator元素之間的分隔符

示例1: 批量查詢(IN條件)

<select id="findByIds" resultType="User">
    SELECT * FROM user WHERE id IN
    <foreach collection="ids" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

示例2: 批量插入

<insert id="batchInsert">
    INSERT INTO user (name, age) VALUES
    <foreach collection="list" item="user" separator=",">
        (#{user.name}, #{user.age})
    </foreach>
</insert>

常見坑點(diǎn): collection 默認(rèn)支持 list、arraymap。如果是自定義參數(shù)名,需要使用 @Param 注解指定。

5.<trim>– 自定義前綴/后綴處理

<where><set> 本質(zhì)上都是 <trim> 的快捷方式,當(dāng)需要更精細(xì)的控制時可直接使用 <trim>。

屬性:

  • prefix – 整體前添加的字符串
  • suffix – 整體后添加的字符串
  • prefixOverrides – 去除前綴中的指定字符串
  • suffixOverrides – 去除后綴中的指定字符串

等價關(guān)系:

<!-- <where> 等價于 -->
<trim prefix="WHERE" prefixOverrides="AND |OR ">
    ...
</trim>

<!-- <set> 等價于 -->
<trim prefix="SET" suffixOverrides=",">
    ...
</trim>

自定義示例: 動態(tài)添加 ORDER BY 子句

<select id="selectWithOrder" resultType="User">
    SELECT * FROM user
    <trim prefix="ORDER BY" suffixOverrides=",">
        <if test="orderByName">name,</if>
        <if test="orderByAge">age,</if>
    </trim>
</select>

6.<choose> / <when> / <otherwise>– 分支選擇

類似Java的 switch-case,只執(zhí)行第一個滿足條件的分支。

示例: 按優(yōu)先級排序查詢(姓名優(yōu)先,否則年齡,否則默認(rèn))

<select id="findUsersWithPriority" resultType="User">
    SELECT * FROM user
    <where>
        <choose>
            <when test="name != null">
                AND name LIKE CONCAT('%', #{name}, '%')
            </when>
            <when test="age != null">
                AND age = #{age}
            </when>
            <otherwise>
                AND status = 'ACTIVE'
            </otherwise>
        </choose>
    </where>
</select>

四、綜合實(shí)戰(zhàn):員工管理系統(tǒng)動態(tài)查詢

下面是一個結(jié)合多個標(biāo)簽的完整示例:

<mapper namespace="com.example.EmployeeMapper">
    
    <!-- 動態(tài)查詢員工 -->
    <select id="searchEmployees" resultType="Employee">
        SELECT * FROM employee
        <where>
            <if test="deptId != null">
                AND dept_id = #{deptId}
            </if>
            <if test="minSalary != null">
                AND salary >= #{minSalary}
            </if>
            <if test="maxSalary != null">
                AND salary &lt;= #{maxSalary}
            </if>
            <if test="keywords != null and keywords != ''">
                AND (name LIKE CONCAT('%', #MyBatis動態(tài)SQL封裝,MyBatis動態(tài)SQL使用,MyBatis動態(tài)SQL,MyBatis?SQL, '%')
                     OR position LIKE CONCAT('%', #MyBatis動態(tài)SQL封裝,MyBatis動態(tài)SQL使用,MyBatis動態(tài)SQL,MyBatis?SQL, '%'))
            </if>
            <choose>
                <when test="hireDateStart != null and hireDateEnd != null">
                    AND hire_date BETWEEN #{hireDateStart} AND #{hireDateEnd}
                </when>
                <when test="hireDateStart != null">
                    AND hire_date >= #{hireDateStart}
                </when>
                <when test="hireDateEnd != null">
                    AND hire_date &lt;= #{hireDateEnd}
                </when>
            </choose>
        </where>
        <if test="orderBy != null">
            <trim prefix="ORDER BY" suffixOverrides=",">
                <if test="orderBy.name">name,</if>
                <if test="orderBy.salary">salary,</if>
                <if test="orderBy.hireDate">hire_date,</if>
            </trim>
        </if>
    </select>
    
</mapper>

五、最佳實(shí)踐與常見問題

推薦做法

  • 優(yōu)先使用 <where>/<set> 而非手寫 1=1SET 后跟逗號。
  • 結(jié)合 <trim> 處理復(fù)雜的動態(tài)前綴/后綴邏輯。
  • 使用 @Param 為集合參數(shù)命名,避免依賴默認(rèn)的 list/array。
  • 對字符串判空test="name != null and name != ''"

常見錯誤

錯誤現(xiàn)象原因解決方案
動態(tài)SQL不生效忘記在<select>中嵌入動態(tài)標(biāo)簽檢查標(biāo)簽是否正確嵌套
多余的AND/OR條件未全部滿足時前綴殘留使用<where><trim prefixOverrides>
批量插入性能差foreach生成超大SQL改用分批處理或JDBC batch
OGNL表達(dá)式異常使用了Java的&&/`

六、總結(jié)

MyBatis的動態(tài)SQL通過一套簡潔的XML標(biāo)簽,完美解決了傳統(tǒng)JDBC拼接SQL的痛點(diǎn)。掌握以下核心標(biāo)簽即可應(yīng)對90%的動態(tài)場景:

標(biāo)簽核心用途
<if>簡單條件判斷
<where>智能查詢條件組裝
<set>智能更新字段組裝
<foreach>遍歷集合(IN、批量操作)
<trim>自定義前綴/后綴處理
<choose>多分支互斥選擇

動態(tài)SQL的本質(zhì)是在XML層面基于OGNL表達(dá)式進(jìn)行零邏輯的SQL片段組合。理解這一思想后,你可以靈活組合這些標(biāo)簽,寫出既優(yōu)雅又安全的動態(tài)SQL。

延伸思考: 如果動態(tài)條件非常復(fù)雜(超過5個分支),建議考慮將部分邏輯遷移到Java層,使用@SelectProvider注解或構(gòu)建查詢對象模式,以保持XML的可讀性。

到此這篇關(guān)于一文詳解MyBatis中動態(tài)SQL的封裝原理與常用標(biāo)簽實(shí)戰(zhàn)應(yīng)用的文章就介紹到這了,更多相關(guān)MyBatis動態(tài)SQL應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springcloud 熔斷監(jiān)控Hystrix Dashboard和Turbine

    springcloud 熔斷監(jiān)控Hystrix Dashboard和Turbine

    這篇文章主要介紹了springcloud 熔斷監(jiān)控Hystrix Dashboard和Turbine,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 基于SpringMVC攔截器實(shí)現(xiàn)接口耗時監(jiān)控功能

    基于SpringMVC攔截器實(shí)現(xiàn)接口耗時監(jiān)控功能

    本文呢主要介紹了基于SpringMVC攔截器實(shí)現(xiàn)的接口耗時監(jiān)控功能,統(tǒng)計接口的耗時情況屬于一個可以復(fù)用的功能點(diǎn),因此這里直接使用 SpringMVC的HandlerInterceptor攔截器來實(shí)現(xiàn),需要的朋友可以參考下
    2024-02-02
  • Java多數(shù)據(jù)源的三種實(shí)現(xiàn)方式小結(jié)

    Java多數(shù)據(jù)源的三種實(shí)現(xiàn)方式小結(jié)

    多數(shù)據(jù)源是在一個應(yīng)用程序中配置和使用多個不同的數(shù)據(jù)庫連接,本文主要介紹了Java多數(shù)據(jù)源的三種實(shí)現(xiàn)方式小結(jié),具有一定的參考價值,感興趣的可以了解一下
    2025-03-03
  • java中TCP/UDP詳細(xì)總結(jié)

    java中TCP/UDP詳細(xì)總結(jié)

    本篇文章對Java中的TCP/UDP知識點(diǎn)進(jìn)行了歸納總結(jié)分析。需要的朋友參考下
    2017-04-04
  • FileOutputStream文件寫入類實(shí)現(xiàn)方式

    FileOutputStream文件寫入類實(shí)現(xiàn)方式

    這篇文章主要介紹了FileOutputStream文件寫入類實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2026-03-03
  • SpringBoot項(xiàng)目新建的五種方式詳解

    SpringBoot項(xiàng)目新建的五種方式詳解

    本文介紹了SpringBoot項(xiàng)目創(chuàng)建的五種主流方式,包括IDEA+Spring官方腳手架、Spring官網(wǎng)下載壓縮包、IDEA+阿里云腳手架、阿里云官網(wǎng)下載壓縮包和普通MavenJava項(xiàng)目改造為SpringBoot項(xiàng)目,每種方式都有其適用場景、操作步驟、優(yōu)點(diǎn)和缺點(diǎn),并總結(jié)了五種方式的對比
    2026-01-01
  • SpringBoot整合ES解析搜索返回字段問題

    SpringBoot整合ES解析搜索返回字段問題

    這篇文章主要介紹了SpringBoot整合ES解析搜索返回字段問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • JDK反序列化時修改類的全限定性名解析

    JDK反序列化時修改類的全限定性名解析

    這篇文章主要介紹了JDK反序列化時修改類的全限定性名解析,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Java實(shí)現(xiàn)文件上傳保存

    Java實(shí)現(xiàn)文件上傳保存

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)文件上傳保存,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Spring boot 數(shù)據(jù)庫連接斷線重連問題

    Spring boot 數(shù)據(jù)庫連接斷線重連問題

    這篇文章主要介紹了Spring boot 數(shù)據(jù)庫連接斷線重連問題,需要的朋友可以參考下
    2017-06-06

最新評論

儋州市| 鲜城| 蓝田县| 大方县| 长子县| 集贤县| 安仁县| 信丰县| 兖州市| 莎车县| 芦山县| 莱阳市| 舒兰市| 崇义县| 锡林浩特市| 铜陵市| 涞源县| 古浪县| 灌阳县| 库尔勒市| 泾川县| 嘉鱼县| 中宁县| 宜兰市| 蒲江县| 兴仁县| 合川市| 呼图壁县| 榆社县| 临沧市| 马龙县| 博白县| 宜都市| 沁阳市| 平舆县| 镶黄旗| 嘉祥县| 外汇| 石棉县| 休宁县| 临颍县|