1. 程式人生 > >MyBatis使用大全(4)------動態SQL使用

MyBatis使用大全(4)------動態SQL使用

MyBatis 的強大特性之一便是它的動態 SQL。

如果你用jdbc等等每次拼接sql都需要特別注意空格,未列的逗號。

但是,利用MyBatis動態SQL對於這些問題會有一些改善,用起來會

相對省心。通常使用動態 SQL 不可能是獨立的一部分,

MyBatis當然使用一種強大的動態 SQ 語言來改進這種情形,

這種語言可以被用在任意的 SQL 對映語句中。

動態 SQL 元素和使用 JSTL 或其他類似基於 XML 的文字處理器相似。

在 MyBatis 之前的版本中,有很多的元素需要來了解。

MyBatis 3 大大提升了它們,現在用不到原先一半的元素就可以。

MyBatis 採用功能強大的基於 OGNL 的表示式來消除其他元素。

常用元素如下:

--if

--choose (when, otherwise)

--trim (where, set)

--foreach

接下來對這些元素進行討論:

(1) if的使用

動態 SQL 通常要做的事情是有條件地包含 where 子句的一部分。比如:

Java程式碼查詢方法封裝引數map:

  1. Map<String,Object> parMap = new HashMap<String, Object>();  
  2. parMap.put("id"1);  
  3. UserMainMapper userMainMapper = session.getMapper(UserMainMapper.class
    );  
  4. User user = userMainMapper.queryUserMainById(parMap);  
  5. System.out.println(user.getUsername());  
對應的對映檔案查詢方法:
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE mapper    
  3.   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"    
  4.   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!--   
  6.     為這個mapper指定一個唯一的namespace,namespace的值習慣上設定成包名+去掉sql對映檔案字尾的檔名,  
  7.     這樣就能夠保證namespace的值是唯一的,例如namespace="com.lanhuigu.mybatis.map.UserMainMapper"
  8.     就是com.lanhuigu.mybatis.map(包名)+UserMainMapper(UserMainMapper.xml檔案去除字尾)  
  9. -->
  10. <mappernamespace="com.lanhuigu.mybatis.map.UserMainMapper">
  11.   <!--  
  12.      在select標籤中編寫查詢的SQL語句, 設定select標籤的id屬性為queryUserMainById,id屬性值必須是唯一的,  
  13.      不能夠重複使用parameterType屬性指明查詢時使用的引數型別,resultType屬性指明查詢返回的結果集型別  
  14.      resultType="com.lanhuigu.mybatis.entity.User"就表示將查詢結果封裝成一個User類的物件返回  
  15.      User類就是users表所對應的實體類  
  16.   -->
  17.   <selectid="queryUserMainById"parameterType="java.util.Map"
  18.           resultType="com.lanhuigu.mybatis.entity.User">
  19.      select     
  20.         f_id id,    
  21.         f_username username,    
  22.         f_age age    
  23.      from t_user_main     
  24.      where 1=1
  25.      <iftest="id != null">
  26.         and f_id = #{id}  
  27.      </if>
  28.   </select>
  29. </mapper>
在該查詢方法中,parameterType="java.util.Map"指定傳入引數的型別為map,

在where條件後,我們加了一個對id是否為空的判斷,如果不為空,則作為查詢條件之一,

否則,不做為查詢條件。

當然了,我們能判斷一個條件,我們也能判斷多個條件,比如map多封裝幾個有用的引數,

查詢條件同樣可以進行拆分或組合判斷。

比如map封裝:

  1. Map<String,Object> parMap = new HashMap<String, Object>();  
  2. parMap.put("id"1);  
  3. parMap.put("username""testMyBatis");  
查詢條件if判斷部分做修改:
  1. <selectid="queryUserMainById"parameterType="java.util.Map"
  2.           resultType="com.lanhuigu.mybatis.entity.User">
  3.    select     
  4.       f_id id,    
  5.       f_username username,    
  6.       f_age age    
  7.    from t_user_main     
  8.    where 1=1
  9.    <iftest="id != null and username!=null">
  10.     and f_id = #{id}  
  11.     and f_username = #{username}  
  12.    </if>
  13. </select>
我們可以看到,在以前id判斷基礎條件上加了一個username的判斷。

注意:對於if的應用我們可以根據實際情況判斷,可以單個判斷,可以多個條件判斷。

2.choose, when, otherwise的使用

有些時候,我們不想用到所有的條件語句,而只想從中擇其一二。

針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。

這種處理方式在Oracle,MySQL資料庫中條件判斷邏輯一樣。咱們講上面例子改改,例如:

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE mapper    
  3.   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"    
  4.   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!--   
  6.     為這個mapper指定一個唯一的namespace,namespace的值習慣上設定成包名+去掉sql對映檔案字尾的檔名,  
  7.     這樣就能夠保證namespace的值是唯一的,例如namespace="com.lanhuigu.mybatis.map.UserMainMapper"
  8.     就是com.lanhuigu.mybatis.map(包名)+UserMainMapper(UserMainMapper.xml檔案去除字尾)  
  9. -->
  10. <mappernamespace="com.lanhuigu.mybatis.map.UserMainMapper">
  11.   <!--  
  12.      在select標籤中編寫查詢的SQL語句, 設定select標籤的id屬性為queryUserMainById,id屬性值必須是唯一的,  
  13.      不能夠重複使用parameterType屬性指明查詢時使用的引數型別,resultType屬性指明查詢返回的結果集型別  
  14.      resultType="com.lanhuigu.mybatis.entity.User"就表示將查詢結果封裝成一個User類的物件返回  
  15.      User類就是users表所對應的實體類  
  16.   -->
  17.   <selectid="queryUserMainById"parameterType="java.util.Map"
  18.           resultType="com.lanhuigu.mybatis.entity.User">
  19.      select     
  20.         f_id id,    
  21.         f_username username,    
  22.         f_age age    
  23.      from t_user_main     
  24.      where 1=1
  25.      <choose>
  26.         <whentest="id != null">
  27.             and f_id = #{id}  
  28.         </when>
  29.         <whentest="username != null">
  30.             and f_username = #{username}  
  31.         </when>
  32.         <otherwise>
  33.             and f_id = 10
  34.         </otherwise>
  35.      </choose>
  36.   </select>
  37. </mapper>
邏輯判斷部分很明顯,當id不為空,加上條件,當username不為空加上條件,

但是如果都為空,強制查詢f_id=10的資料。

3.trim, where, set的使用

我在上面的例子中where後面都加1=1,加這個的原因主要是防止生成的sql是這樣的,

select   
        f_id id,  
        f_username username,  
        f_age age  
     from t_user_main   
     where  and f_id = #{id}

這條sql執行的時候必然報錯,我在前面加個1=1就可以輕鬆避免。讓sql避免異常:

select   
        f_id id,  
        f_username username,  
        f_age age  
     from t_user_main   
     where 1=1 and f_id = #{id}

處理這樣的問題還有另外一個方法,使用where元素:

  1. <selectid="queryUserMainById"parameterType="java.util.Map"
  2.           resultType="com.lanhuigu.mybatis.entity.User">
  3.    select     
  4.       f_id id,    
  5.       f_username username,    
  6.       f_age age    
  7.    from t_user_main     
  8.    <where>
  9.     <choose>
  10.         <whentest="id != null">
  11.             f_id = #{id}  
  12.         </when>
  13.         <whentest="username != null">
  14.             and f_username = #{username}  
  15.         </when>
  16.         <otherwise>
  17.             and f_id = 10
  18.         </otherwise>
  19.       </choose>
  20.    </where>
  21. </select>
使用where元素後如上寫法,肉眼上看去,當我們的id為空時,我們是不是會生成這樣的sql:
select   
        f_id id,  
        f_username username,  
        f_age age  
     from t_user_main where and f_username = #{username}

這個sql的where後直接跟了個and執行的時候為什麼不報錯,這都是where元素的功勞。

where知道,有大於等於1個條件時,才會去注入"where"字句,若最後的內容是“AND”或“OR”開頭的,

where 元素也知道如何將他們去除。這就是我們為什麼肉眼看上去and....,這個語句卻能執行的原因。

如果 where 元素沒有按正常套路出牌,我們還是可以通過自定義 trim 元素來定製我們想要的功能。

比如,和 where 元素等價的自定義 trim 元素為:

<trimprefix="WHERE"prefixOverrides="AND |OR "> ...</trim>

prefixOverrides 屬性會忽略通過管道分隔的文字序列(注意此例中的空格也是必要的)。

它帶來的結果就是所有在 prefixOverrides 屬性中指定的內容將被移除,並且插入 prefix 屬性中指定的內容。

類似的用於動態更新語句的解決方案叫做 set。set 元素可以被用於動態包含需要更新的列,而捨去其他的。比如:

  1. <updateid="updateUserMain"parameterType="java.util.Map">
  2.     update t_user_main   
  3.         <set>
  4.             <iftest="username != null">f_username = #{username}</if>
  5.             <iftest="age != null">f_age = #{age}</if>
  6.         </set>
  7.       where f_id = #{id}  
  8. bsp;</update>
這裡,set 元素會動態前置 SET 關鍵字,同時也會消除無關的逗號,

因為用了條件語句之後很可能就會在生成的賦值語句的後面留下這些逗號。

4.foreach的使用

  1. <selectid="queryUserMainById"resultType="com.lanhuigu.mybatis.entity.User">
  2.    select     
  3.       f_id id,    
  4.       f_username username,    
  5.       f_age age    
  6.    from t_user_main     
  7.    where f_id in   
  8.    <foreachcollection="item="item" index="index" collection="list" open="(" separator=","close=")">
  9.       #{item}  
  10.    </foreach>
  11. </select>
foreach 元素的功能是非常強大的,它允許你指定一個集合,宣告可以用在元素體內的集合項和索引變數。

它也允許你指定開閉匹配的字串以及在迭代中間放置分隔符。

這個元素是很智慧的,因此它不會偶然地附加多餘的分隔符。

可以將任何可迭代物件(如列表、集合等)和任何的字典或者陣列物件傳遞給foreach作為集合引數。

當使用可迭代物件或者陣列時,index是當前迭代的次數,item的值是本次迭代獲取的元素。

當使用字典(或者Map.Entry物件的集合)時,index是鍵,item是值。

5.bind的使用

bind 元素可以從 OGNL 表示式中建立一個變數並將其繫結到上下文。比如:

  1. <selectid="queryUserMainById"resultType="com.lanhuigu.mybatis.entity.User">
  2.     <bindname="pattern"value="'%' + _parameter.getUsername() + '%'"/>
  3.  select     
  4.       f_id id,    
  5.       f_username username,    
  6.       f_age age    
  7.    from t_user_main  
  8. where f_username like #{pattern}  
  9. </select>
其實這個繫結一般不用,因為我們有sql元素,用起來更靈活,更方便。

相關推薦

MyBatis使用大全(4)------動態SQL使用

MyBatis 的強大特性之一便是它的動態 SQL。 如果你用jdbc等等每次拼接sql都需要特別注意空格,未列的逗號。 但是,利用MyBatis動態SQL對於這些問題會有一些改善,用起來會 相對省心。通常使用動態 SQL 不可能是獨立的一部分, MyBatis當然使用一種

mybatis教程4(動態SQL)

over ffffff 標簽 oss 分享 when eve http test 動態SQL語句 MyBatis 的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其它類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記添

MyBatis(4)動態SQL

截圖 轉義字符 ram 分隔符 當前 pup efi Opens rep MyBatis 的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其它類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記添加必要的空格,還要註意去

Mybatis框架之動態SQL書寫方式小結

用戶輸入 ... pre efi date emp 表達式 內容 字符 動態SQL簡介 動態SQL是Mybatis框架中強大特性之一。在一些組合查詢頁面,需要根據用戶輸入的查詢條件生成不同的查詢SQL,這在JDBC或其他相似框架中需要在代碼中拼寫SQL,經常容易出錯,在My

mybatis註解開發-動態SQL

sql語句 com jdbc new info ets stat -- -s 實體類以及表結構 在mybatis-config.xml中註冊mapper接口 -------------------------- 動態查詢@SelectProvider Emp

Spring boot 配置 mybatis xml和動態SQL

star too conn -- 動態 div nec output out 1.pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="

mybatis 詳解------動態SQL

soc int 表示 ssi 性別 ace cin override 博客 目錄 1、動態SQL:if 語句 2、動態SQL:if+where 語句 3、動態SQL:if+set 語句 4、動態SQL:choose(when,otherwise) 語句 5、動態SQL

spring boot-mybatis三種動態sql(5)

內部 轉換成 ava .get bat class ide div upd 腳本sql XML配置方式的動態SQL我就不講了,有興趣可以自己了解,下面是用<script>的方式把它照搬過來,用註解來實現。適用於xml配置轉換到註解配置 @Select("&l

MyBatis學習之動態SQL

1、概述 MyBatis最為強大的部分是提供了動態SQL的支援,一些查詢邏輯可以直接在xml中完成,大大簡化了我們的操作,體現出了MyBatis的靈活性、拓展性、和可維護性。 MyBatis中的四大動態SQL元素: if choose (when, otherw

MyBatis解決Update動態SQL逗號的問題

最做專案遇到以下情況,MyBatis中需要動態拼接Update,由於之前忙著趕專案,就直接照著下面的這樣寫,結果發現系統出現了異常,原來這樣寫如果id=null就會出錯 UPDATE TABLE SET <if test=

mybatis 6:動態SQL

※  動態SQL  dynamic-sql         有時候,靜態的SQL語句並不能滿足應用程式的需求。我們可以根據一些條件,來動態地構建 SQL語句。         例如,在Web應用程式中,有可能有一些搜尋介面,需要輸入一個或多個選項,然後根據這些已選擇的條件去

mybatis實踐之動態sql+重用語句塊(include)

1.com.dao(.java+.xml) public interface ShopMapper { List<Shop> queryLike(String shopName); List<Shop> queryByCondi

mybatis框架的動態sql語句

  今天突然聽到動態sql語句這個名字,我想了一下,好像腦袋裡面沒有這個概念;上網查了查,動態和靜態都分別是什麼? 拼接sql語句來實現增刪改查,可以讓程式碼複用性增強; 靜態sql就是平常寫死的sq

MyBatis總結之動態SQL

目錄 1.if 2.choose(when、otherwise) 3.where 4.set 5.foreach 6.bind 1.if  1.1 條件查詢,如引數非空則執行條件: <select id="getByUserName" pa

學習Mybatis(6):動態SQL

五大元素 元素 作用 if 單條件分支判斷 choose(when,otherwise) 多條件分支判斷 trim(where,set)

MyBatis實戰之動態SQL

如果使用JDBC或者其他框架,很多時候你得根據需要去拼接SQL,這是一個麻煩的事情,而MyBatis提供對SQL語句動態的組裝能力,而且它只有幾個基本的元素,非常簡單明瞭,大量的判斷都可以在MyBatis的對映XML檔案裡面配置,以達到許多我們需要大量程式碼才能實現的功能,大大減少了我們編寫程式碼的工作量,這

mybatis自定義動態sql傳入物件

現在有一需求,要求頁面顯示懸賞列表,要求該懸賞未過期,沒有人接受以及附帶分頁查詢。 這裡我們很容易能得到滿足該需求的sql語句: select * from bounty where DeadTime > nowtime AND s

Mybatis---強大的動態SQL

1. if:    你們能判斷,我也能判斷! 作為程式猿,誰不懂 if !  在mybatis中也能用 if 啦: <select id="findUserById" resultType="user"> select * from

MyBatis 詳解 ------ 動態SQL

用mybatis對一張表進行的CRUD操作時,寫的 SQL 語句都比較簡單,如果有比較複雜的業務,寫複雜的 SQL 語句,往往需要拼接,而拼接 SQL ,稍微不注意,由於引號,空格等缺失可能都會導致錯誤。 那麼怎麼去解決這個問題呢?這將使用 MyBatis 動

mybatis四(動態sql)

test 數據庫連接 executor for 類型 轉換 res emp ognl <1><select id="selectUserByConditions" parameterType="user" resultType="user">