欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

帶你重新認(rèn)識MyBatis的foreach

 更新時間:2022年11月01日 08:27:09   作者:BillySir  
這篇文章主要介紹了重新認(rèn)識MyBatis的foreach,本文提出了一種簡化<foreach>寫法的設(shè)想,更重要的是通過解決空集時生成的SQL語法問題,更深刻地理解MyBatis的foreach的生成機制,需要的朋友可以參考下

用了MyBatis的同行,應(yīng)該見過foreach,它一般是這樣用的:

<select id="foreachTest" resultType="Blog">
    select * from t_blog where id in
    <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

難記

有沒有人跟我一樣,覺得

<foreach collection="list" index="index" item="item" open="(" separator="," close=")">

這一串很啰嗦?每次寫<foreach>都因為記不住和怕記不牢,要查找和復(fù)制現(xiàn)有的來改。假如可以簡化,就不至于要這樣了。
一項項來分析:

  • foreach這個是xml標(biāo)簽,少不了。
  • collection可以通過探測參數(shù)類型+數(shù)量,從而在大多數(shù)情況下,知道對應(yīng)哪個參數(shù)而省略。
  • index這個就更加不用寫了,幸好它真的是用時才寫,不用不寫。
  • item假如缺省值就是item,則可能會有一些沖突,比如某個表名叫item,會不會讓人掉坑里才豁然知道緣由?想不清楚。
  • open難道不是通常都是"("嗎?但只要不寫open,缺省值是沒有,即是空串,很無語,強迫我們幾乎每個foreach都要寫open="("
  • separator難道不是絕大多數(shù)都是","嗎?缺省值也是空串,更無語
  • closeopen同理。

空集合問題

還有一個問題,當(dāng)傳入的集合是空集的時候,比如上面這個例子,某些情況計算出來的list是空集合。按道理,既然list是id的集合,空集合意味著應(yīng)該select到0條記錄。但結(jié)果卻是報SQL語法錯誤。原因是生成的SQL長這樣:

select * from t_blog where id in ;      -- 為了明顯,我補了個分號

是的,按SQL語法,in后面的小括號是不能沒有內(nèi)容的,小括號本身也是不能省的,抓狂。

在以前,我接觸的項目有DAO層(指java interface mapper之上的一層),我會在DAO層先判斷,若list是Empty,直接返回空集,否則再執(zhí)行mybatis的查詢。后來的一些項目,推崇簡單化,沒有DAO層,Service直接調(diào)用java interface mapper。把這個“判空返回空”的邏輯寫在Service就顯得別扭。難道MyBatis就不能優(yōu)雅地解決這個問題嗎?

解法

直到后來看到了這種寫法:

<select id="foreachTest" resultType="Blog">
    select * from t_blog
  <where>
    <foreach collection="list" index="index" item="item" open=" id in (" separator="," close=")">
        #{item}
    </foreach>
  </where>
</select>

特別之處在于open="id in (",與一開始的id in寫在foreach外面有什么不同呢?經(jīng)過實驗,結(jié)論是這樣的:

  • 當(dāng)list非空時,兩者并無區(qū)別。
  • 當(dāng)list為空時,既不生成open值,也不生成close值!

所以,當(dāng)list為空時,SQL就是:select * from t_blog,也就沒有違反語法。但是查到的是全部的記錄,而不是預(yù)期的“0條記錄”。
改進(jìn)為這樣寫

<select id="foreachTest" resultType="Blog">
    select * from t_blog
  <where>
    1 = 0 
    <foreach collection="list" index="index" item="item" open=" or id in (" separator="," close=")">
        #{item}
    </foreach>
  </where>
</select>

如果,還有其它的and條件,則需要在or的兩邊加上小括號。

<select id="foreachTest" resultType="Blog">
    select * from t_blog
  <where>
    (1 = 0 
    <foreach collection="list" index="index" item="item" open=" or id in (" separator="," close=")">
        #{item}
    </foreach>
    )
    and ...
  </where>
</select>

這樣,不論list是否empty,都會生成正確語法和功能的SQL語句。有興趣的朋友可自行推導(dǎo)。

優(yōu)雅的解法

但我覺得上面的寫法不夠優(yōu)雅,經(jīng)過實驗,找到一種我認(rèn)為更優(yōu)雅的寫法:

<select id="foreachTest" resultType="Blog">
    select * from t_blog
  <where>
    <foreach collection="list" index="index" item="item" open=" and id in (" close="-1)">
        #{item},
    </foreach>
    and ...
  </where>
</select>

留意:

  • separator沒了,缺省就是空串
  • #{item}后面有了個逗號(,)
  • close里多了個-1

是這樣的思路,我們要解決的是in后面是空的問題,假如在list為empty時,也能“塞”入一個不存在的值,比如這里規(guī)定id不可能是-1,那么生成的sql就是where id in (-1),語法沒錯,且查不到數(shù)據(jù)。而當(dāng)list非空時,生成的sql如where id in (1,2,3,-1),雖然有-1,但不影響查出來的結(jié)果。只是本來3是最后一個,不需要加逗號,由于后面固定有-1,所以每個#{item}后面固定要有逗號,如果逗號放在separator,則只出現(xiàn)在各個id之間,放在#{item}就可以出現(xiàn)在每個item后了。

通過此案例,回頭一看,思路一下子就打開了。open里的寫法可以很靈活,只要符合SQL語法的,理論上都可以往open里放。separatorclose也一樣。可能作者就是因為這些靈活的用法,所以干脆讓它們的缺省值是空串。這本無標(biāo)準(zhǔn),所以不能說這樣做就是對或錯的。

一種簡化<foreach>的設(shè)想

但如果允許我修改設(shè)計的話,我會讓open的缺省值為"(",separator的缺省值為", ",close的缺省值為")"。因為大多數(shù)情況下它們的值就是這樣。假如特殊情況下,就想要它的值為空串,可以這么寫open="",何嘗不可。這樣做的好處是,通常情況下foreach會很簡潔:

<foreach collection="list" item="item">
    #{item}
</foreach>

例如,像文章開頭分析的那樣,還可以去掉collection,甚至是item,那成為這樣的極簡:

<foreach>
    #{item}
</foreach>

整體這樣:

<select id="foreachTest" resultType="Blog">
    select * from t_blog where id in
    <foreach>
        #{item}
    </foreach>
</select>

簡化成這樣,誰還不敢直接寫<foreach>了?

總結(jié)

本文提出了一種簡化<foreach>寫法的設(shè)想,更重要的是通過解決空集時生成的SQL語法問題,更深刻地理解MyBatis的foreach的生成機制。打開思路,更靈活地利用open、separator、close,得到符合預(yù)期的SQL,還兼顧到代碼的優(yōu)雅。

到此這篇關(guān)于重新認(rèn)識MyBatis的foreach的文章就介紹到這了,更多相關(guān)MyBatis的foreach內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java并發(fā)編程之CountDownLatch源碼解析

    Java并發(fā)編程之CountDownLatch源碼解析

    這篇文章主要介紹了Java并發(fā)編程之CountDownLatch源碼解析,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java并發(fā)編程的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-04-04
  • JS求多個數(shù)組的重復(fù)數(shù)據(jù)

    JS求多個數(shù)組的重復(fù)數(shù)據(jù)

    這篇文章主要介紹了JS求多個數(shù)組的重復(fù)數(shù)據(jù)的辦法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java基于正則表達(dá)式實現(xiàn)xml文件的解析功能詳解

    Java基于正則表達(dá)式實現(xiàn)xml文件的解析功能詳解

    這篇文章主要介紹了Java基于正則表達(dá)式實現(xiàn)xml文件的解析功能,結(jié)合實例形式分析了java使用正則表達(dá)式針對xml文件節(jié)點的相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • SpringBoot整合第三方技術(shù)的實現(xiàn)

    SpringBoot整合第三方技術(shù)的實現(xiàn)

    本文主要介紹了SpringBoot整合第三方技術(shù)的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • 一個處理用戶登陸的servlet簡單實例

    一個處理用戶登陸的servlet簡單實例

    這篇文章主要介紹了一個處理用戶登陸的servlet簡單實例,可通過servlet實現(xiàn)處理用戶登錄的功能,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-01-01
  • springboot rabbitmq整合rabbitmq之消息持久化存儲問題

    springboot rabbitmq整合rabbitmq之消息持久化存儲問題

    這篇文章主要介紹了springboot rabbitmq整合rabbitmq之消息持久化存儲問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • java實現(xiàn)俄羅斯方塊游戲

    java實現(xiàn)俄羅斯方塊游戲

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)俄羅斯方塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 關(guān)于Java整合RabbitMQ實現(xiàn)生產(chǎn)消費的7種通訊方式

    關(guān)于Java整合RabbitMQ實現(xiàn)生產(chǎn)消費的7種通訊方式

    這篇文章主要介紹了關(guān)于Java整合RabbitMQ實現(xiàn)生產(chǎn)消費的7種通訊方式,消息中間件是基于隊列與消息傳遞技術(shù),在網(wǎng)絡(luò)環(huán)境中為應(yīng)用系統(tǒng)提供同步或異步、可靠的消息傳輸?shù)闹涡攒浖到y(tǒng),需要的朋友可以參考下
    2023-05-05
  • Spring中一個少見的引介增強IntroductionAdvisor

    Spring中一個少見的引介增強IntroductionAdvisor

    這篇文章主要為大家介紹了Spring中一個少見的引介增強IntroductionAdvisor實戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java基礎(chǔ)教程之基本類型數(shù)據(jù)類型、包裝類及自動拆裝箱

    Java基礎(chǔ)教程之基本類型數(shù)據(jù)類型、包裝類及自動拆裝箱

    這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)教程之基本類型數(shù)據(jù)類型、包裝類及自動拆裝箱的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評論