MyBatis 動態SQL

来源:https://www.cnblogs.com/chy18883701161/archive/2020/01/06/12156667.html
-Advertisement-
Play Games

動態SQl是MyBatis的強大特性之一,可以完成對SQL語句的動態組裝。 比如說傳入一個User對象,要根據這個User中的數據查詢用戶的完整信息: 如果User對象中只有name屬性有值,sql語句是:select * from user_tb where name=#{name} 如果User ...


 

動態SQl是MyBatis的強大特性之一,可以完成對SQL語句的動態組裝。

 

比如說傳入一個User對象,要根據這個User中的數據查詢用戶的完整信息:

  • 如果User對象中只有name屬性有值,sql語句是:select * from user_tb  where name=#{name}
  • 如果User對象中只有tel屬性有值,sql語句是:select * from user_tb where tel=#{tel}
  • 如果User對象的name、tel都有值,sql語句是:select * from user_tb where name=#{name} and tel=#{tel}

有時候sql語句不是一成不變的,要根據傳入的數據動態生成要執行的sql語句,動態sql就適合這種情況。

 

最好將日誌的控制台輸出級別設置為DEBUG,這樣在控台能看到SQL語句。

 

 


 

 

MyBatis中的動態sql元素

  • <if>    相當於java中的if,用於單分支的條件判斷
  • <choose>、<when>、<otherwise>   相當於java中的switch...case...default,用於多分支的條件判斷,從多個選項中選擇一個
  • <foreach>  迴圈,常和sql的in語句搭配使用
  • <where>、<trim>、<set>    輔助元素,用於一些處理sql拼裝、特殊字元的問題
  • <bind>   從OGNL表達式中創建一個變數,並將其綁定到上下文,常用於模糊查詢

 

 


 

 

<where>、<if>的使用

<select id="queryUser" parameterType="user" resultType="user">
         SELECT * FROM user_tb
         <where>
            <if test="name!=null and name!=''">
                name=#{name}
            </if>
            <if test="tel!=null and tel!=''">
                AND tel=#{tel}
            </if>
        </where>
</select>

<where>相當於sql語句中的關鍵字WHERE。

<if>中的test表示條件,條件成立就把元素體中的字元串拼接到sql語句中,否則不拼接。

tel不進行數學運算,使用字元串類型。

 

 

<where>中有<if>成立時,<where>才會在sql語句中添加WHERE關鍵字,否則不添加。

<where>會自動剔除元素體中多餘的AND、OR。

比如傳入的User對象只設置了tel,拼接的sql語句是:SELECT  *  FROM  user_tb  WHERE  AND  tel=#{tel},<where>會自動剔除多餘的AND。

 

 

不使用<where>的寫法:

<select id="queryUser" parameterType="user" resultType="user">
         SELECT * FROM user_tb  WHERE 1=1
            <if test="name!=null and name!=''">
                AND name=#{name}
            </if>
            <if test="tel!=null and tel!=''">
                AND tel=#{tel}
            </if>
</select>

 

<where>會自動去掉多餘的AND,但不會自動加上缺少的AND,我們通常在每個<if>中都加上AND,防止把AND寫掉了。

 

 


 

 

<trim>的使用

<trim>可以定製需要的功能,比如使用<trim>達到<where>的效果:

<select id="queryUser" parameterType="user" resultType="user">
         SELECT * FROM user_tb
         <trim prefix="WHERE" prefixOverrides="AND">
            <if test="name!=null and name!=''">
                name=#{name}
            </if>
            <if test="tel!=null and tel!=''">
                AND tel=#{tel}
            </if>
         </trim>
</select>

prefix會在這段字元串之前加上指定的首碼,如果裡面的<if>都不滿足條件,則不加首碼。

prefixOverrides指定要去除的多餘的字元串。

 

 


 

 

<choose>、<when>、<otherwise>的使用

有時候我們只需要從多個選項中選擇一個,比如登錄教務系統,讓你選擇角色:資料庫管理員、教職工、學生:

<select id="queryPwd" parameterType="user" resultType="string">
         SELECT password FROM user_tb WHERE name=#{name}
         <choose>
             <when test="role=='admin'">
                 AND role='admin'
             </when>
             <when test="role=='teacher'">
                 AND role='teacher'
             </when>
             <when test="role=='student'">
                 AND role='student'
             </when>
         </choose>
</select>

 

 

傳入的值是admin、teacher、student,資料庫中的role欄位也是這幾個值,這種傳入的值和資料庫中存儲的值一致的可以直接這樣寫:

<select id="queryPwd" parameterType="user" resultType="string">
         SELECT password FROM user_tb WHERE name=#{name} AND role=#{role}
</select>

如果不一致,比如性別,傳入的是male、female,資料庫中存儲的是0、1,就需要使用<choose>轉換一下。

 

 

    <choose>
             <when test="">
                 
             </when>
             <when test="">
                 
             </when>
             <otherwise>
                 
             </otherwise>
    </choose>

<choose>相當於switch,<when>相當於case,<otherwise>相當於default。

 

 


 

 

 

<set>的使用

更新操作傳入一個pojo類的對象,但我們並不知道哪些屬性是有值的(需要更新的),不能更新全部欄位,因為有的欄位沒有手動賦值,不能用JVM賦的null、0去覆蓋數據表中原來的值。

<set>可解決此問題:

<select id="updateUser" parameterType="user">
         UPDATE user_tb
         <set>
             <if test="name!=null and name!=''">
                 name=#{name},
             </if>
             <if test="tel!=null and tel!=''">
                 tel=#{tel},
             </if>
             <if test="address!=null and address!=''">
                 name=#{name},
             </if>
         </set>
         where id=#{id}
 </select>

<set>用於傳入pojo類型,更新數據表的多個欄位。先判斷欄位是否有值,有值才更新該欄位。

<set>用於更新操作,會自動在這段字元串前面加sql關鍵字“SET”(裡面有<if>為真),並自動去除多餘的逗號(一般自己寫第一個<if>,然後copy下來改,最後面往往會多一個逗號)。

如果裡面的<if>都為假,即沒有要更新的欄位,不會自動在前面加”SET”,此時這個update語句有語法錯誤,會報錯,所以要保證至少有一個欄位需要更新。

 

 


 

 

 

test屬性的註意點

  • 相等判斷:==,!=
  • 邏輯與:只能用and,不能用&&
  • 邏輯或:or、||均可

 

 


 

 

 

<foreach>的使用

<foreach>用於迭代集合、數組,常和in搭配使用。

比如按照手機號隨機抽取3位幸運觀眾(根據手機號碼查詢用戶信息):

<select id="queryUser" parameterType="list" resultType="user">
         SELECT * FROM user_tb WHERE tel IN
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
</select>
        ArrayList<String> telList = new ArrayList<>();
        telList.add("110");
        telList.add("119");
        telList.add("120");
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.queryUser(telList);
        System.out.println(userList);    

 

  • collection   要迭代的數據類型,數組=>array,List=>list,Map=>Map的key的數據類型。使用數組容易出錯,儘量用List代替數組。
  • index   本次迭代的下標,指定一個臨時變數表示下標
  • item   本次迭代的元素,指定一個臨時變數表示本次迭代的元素
  • open   拼接這段字元串時以什麼開頭
  • close  拼接這段字元串以什麼結尾
  • separator   迭代的元素之間用什麼連接(分隔)

collection是必需的,其餘均可選。

 

 

更嚴謹的寫法:

<select id="queryUser" parameterType="list" resultType="user">
         SELECT * FROM user_tb WHERE tel IN
         <if test="list!=null and list.size>0">
             <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
                 #{item}
             </foreach>
         </if>
</select>

如果傳入的是List類型,要使用List對象本身時,約定使用list表示List對象本身。

 

 


 

 

 

<bind>的使用

模糊查詢時可以使用${}連接字元串,但不能防止sql註入。

mysql可以使用concat()連接字元串,oracle可以使用||連接字元串,但只能針對特定的資料庫使用,不利於項目移植。

mybatis的<bind>元素可以解決以上問題。

<select id="queryUser" parameterType="string" resultType="user">
        <bind name="pattern_name" value="'%'+name+'%'"/>
        SELECT * FROM user_tb WHERE name LIKE #{pattern_name}
</select>

<bind>定義一個變數,拼接好字元串。

在sql語句中引用該變數的值。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • LineNumberTable 屬性表存放方法的行號信息 ;屬於調試信息,不是運行時必需的。在使用javac編譯器編譯Java程式時,預設會在class文件中生成這些信息。可以使用javac提供的-g:none選項來關閉該信息的生成 ...
  • 0-前言 碼農人生,實踐為王!在介紹spring cloud之前,先不談理論,先教大家怎麼新建項目以及打包發佈; 實際開發中,我們基本都是用多模塊的的方式構建項目,尤其微服務中,一個系統拆分成很多個微服務項目,在加上基礎模塊,那一個系統的模塊項目就不少了,這個時候,肯定得需要用多模塊的方式構建項目, ...
  • 前言 保留小數位是我們經常會碰到的問題,尤其是刷題過程中。那麼在python中保留小數位的方法也非常多,但是筆者的原則就是什麼簡單用什麼,因此這裡介紹幾種比較簡單實用的保留小數位的方法: 方法一:format函數 >>> print('{:.3f}'.format(1.23456)) 1.235 > ...
  • 本系列筆記主要基於《深入理解Java虛擬機:JVM高級特性與最佳實踐 第2版》,是這本書的讀書筆記。 JVM的參數類型,大致可以分為標準參數、X參數、XX參數,而XX參數又可以分為Boolean類型、非Boolean類型。 標準參數 標準參數就是各個JVM的版本中不變的,相對穩定的參數。 例如: < ...
  • Java選擇結構,Java迴圈結構,return、break、continue ...
  • parameterType、resultType的數據類型要寫全限定類名或者別名。 mybatis已經給常用的數據類型起好了別名,參考mybatis.pdf 3.1.1小節: 基本數據類型很少用,一般都是用包裝類。總結下來就是:字母全小寫。 ...
  • 這篇文章介紹的內容是關於PHP 經典面試題集 PHP 經典面試題集,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下 結合我自己面試情況,面對的一些php面試題列舉出來,基本上結合自己的看法回答的,不妥的地方請大家指出去,與大家一起討論分析,也希望能幫到正在面試的童鞋們: 1.表單提交中 ...
  • MATLAB用“fitgmdist”函數擬合高斯混合模型(一維數據) 作者:凱魯嘎吉 - 博客園 http://www.cnblogs.com/kailugaji/ 在MATLAB中“fitgmdist”的用法及其GMM聚類演算法中介紹過"fitgmdist"函數的用法,這次用"fitgmdist"擬 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...