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

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

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

用了MyBatis的同行,應(yīng)該見(jiàn)過(guò)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>

難記

有沒(méi)有人跟我一樣,覺(jué)得

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

這一串很啰嗦?每次寫<foreach>都因?yàn)橛洸蛔『团掠洸焕?,要查找和?fù)制現(xiàn)有的來(lái)改。假如可以簡(jiǎn)化,就不至于要這樣了。
一項(xiàng)項(xiàng)來(lái)分析:

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

空集合問(wèn)題

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

select * from t_blog where id in ;      -- 為了明顯,我補(bǔ)了個(gè)分號(hào)

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

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

解法

直到后來(lái)看到了這種寫法:

<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 (",與一開(kāi)始的id in寫在foreach外面有什么不同呢?經(jīng)過(guò)實(shí)驗(yàn),結(jié)論是這樣的:

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

所以,當(dāng)list為空時(shí),SQL就是:select * from t_blog,也就沒(méi)有違反語(yǔ)法。但是查到的是全部的記錄,而不是預(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的兩邊加上小括號(hào)。

<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,都會(huì)生成正確語(yǔ)法和功能的SQL語(yǔ)句。有興趣的朋友可自行推導(dǎo)。

優(yōu)雅的解法

但我覺(jué)得上面的寫法不夠優(yōu)雅,經(jīng)過(guò)實(shí)驗(yàn),找到一種我認(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沒(méi)了,缺省就是空串
  • #{item}后面有了個(gè)逗號(hào)(,)
  • close里多了個(gè)-1

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

通過(guò)此案例,回頭一看,思路一下子就打開(kāi)了。open里的寫法可以很靈活,只要符合SQL語(yǔ)法的,理論上都可以往open里放。separator、close也一樣??赡茏髡呔褪且?yàn)檫@些靈活的用法,所以干脆讓它們的缺省值是空串。這本無(wú)標(biāo)準(zhǔn),所以不能說(shuō)這樣做就是對(duì)或錯(cuò)的。

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

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

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

例如,像文章開(kāi)頭分析的那樣,還可以去掉collection,甚至是item,那成為這樣的極簡(jiǎn):

<foreach>
    #{item}
</foreach>

整體這樣:

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

簡(jiǎn)化成這樣,誰(shuí)還不敢直接寫<foreach>了?

總結(jié)

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

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

相關(guān)文章

  • Java使用Jasypt進(jìn)行加密和解密的技術(shù)指南

    Java使用Jasypt進(jìn)行加密和解密的技術(shù)指南

    Jasypt (Java Simplified Encryption) 是一個(gè)簡(jiǎn)化 Java 應(yīng)用中加密工作的庫(kù),它支持加密和解密操作,易于與 Spring Boot 集成,通過(guò) Jasypt,可以安全地管理敏感信息,比如數(shù)據(jù)庫(kù)密碼、API 密鑰等,本文介紹了Java使用Jasypt進(jìn)行加密和解密的技術(shù)指南,需要的朋友可以參考下
    2025-03-03
  • springboot2.x集成swagger的方法示例

    springboot2.x集成swagger的方法示例

    這篇文章主要介紹了springboot2.x集成swagger的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Java基于迭代器模式實(shí)現(xiàn)的訪問(wèn)人員列表操作示例

    Java基于迭代器模式實(shí)現(xiàn)的訪問(wèn)人員列表操作示例

    這篇文章主要介紹了Java基于迭代器模式實(shí)現(xiàn)的訪問(wèn)人員列表操作,簡(jiǎn)單描述了迭代器模式的概念、原理以及使用迭代器模式實(shí)現(xiàn)訪問(wèn)人員列表的相關(guān)操作技巧,需要的朋友可以參考下
    2018-05-05
  • SpringBoot3集成ElasticSearch的方法詳解

    SpringBoot3集成ElasticSearch的方法詳解

    Elasticsearch是一個(gè)分布式、RESTful風(fēng)格的搜索和數(shù)據(jù)分析引擎,適用于各種數(shù)據(jù)類型,數(shù)字、文本、地理位置、結(jié)構(gòu)化數(shù)據(jù)、非結(jié)構(gòu)化數(shù)據(jù),本文給大家詳解介紹了SpringBoot3集成ElasticSearch的方法,需要的朋友可以參考下
    2023-08-08
  • Spring Boot簡(jiǎn)介與快速搭建詳細(xì)步驟

    Spring Boot簡(jiǎn)介與快速搭建詳細(xì)步驟

    SpringBoot其本身沒(méi)有添加什么新的技術(shù),就是整合了一些現(xiàn)有的框架,并提供了一些默認(rèn)的配置,就是這些默認(rèn)的配置,極大的提高了我們的開(kāi)發(fā)效率。這篇文章主要介紹了Spring Boot簡(jiǎn)介與快速搭建,需要的朋友可以參考下
    2021-05-05
  • SpringBoot向容器注冊(cè)bean的方法詳解

    SpringBoot向容器注冊(cè)bean的方法詳解

    這篇文章主要利用示例為大家詳細(xì)介紹了SpringBoot如何向容器注冊(cè)bean(即:將對(duì)象加入容器)的四種方法,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-05-05
  • java中將一個(gè)List等分成n個(gè)list的工具方法(推薦)

    java中將一個(gè)List等分成n個(gè)list的工具方法(推薦)

    下面小編就為大家?guī)?lái)一篇java中將一個(gè)List等分成n個(gè)list的工具方法(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • Java抽象類和普通類區(qū)別、 數(shù)組跟List的區(qū)別解析

    Java抽象類和普通類區(qū)別、 數(shù)組跟List的區(qū)別解析

    這篇文章主要介紹了Java抽象類和普通類區(qū)別、 數(shù)組跟List的區(qū)別,在這里需要注意List是一個(gè)接口,不能直接實(shí)例化,需要使用具體的實(shí)現(xiàn)類來(lái)創(chuàng)建對(duì)象,本文結(jié)合示例代碼介紹的非常詳細(xì),需要的朋友參考下吧
    2023-09-09
  • SpringBoot日程管理Quartz與定時(shí)任務(wù)Task實(shí)現(xiàn)詳解

    SpringBoot日程管理Quartz與定時(shí)任務(wù)Task實(shí)現(xiàn)詳解

    定時(shí)任務(wù)是企業(yè)級(jí)開(kāi)發(fā)中必不可少的組成部分,諸如長(zhǎng)周期業(yè)務(wù)數(shù)據(jù)的計(jì)算,例如年度報(bào)表,諸如系統(tǒng)臟數(shù)據(jù)的處理,再比如系統(tǒng)性能監(jiān)控報(bào)告,還有搶購(gòu)類活動(dòng)的商品上架,這些都離不開(kāi)定時(shí)任務(wù)。本節(jié)將介紹兩種不同的定時(shí)任務(wù)技術(shù)
    2022-09-09
  • java.lang.IllegalStateException異常原因和解決辦法

    java.lang.IllegalStateException異常原因和解決辦法

    這篇文章主要給大家介紹了關(guān)于java.lang.IllegalStateException異常原因和解決辦法,IllegalStateException是Java標(biāo)準(zhǔn)庫(kù)中的一個(gè)異常類,通常表示在不合適或無(wú)效的情況下執(zhí)行了某個(gè)方法或操作,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

隆化县| 新田县| 宝坻区| 崇明县| 拜泉县| 泌阳县| 宁津县| 罗定市| 廉江市| 双峰县| 凤台县| 穆棱市| 石嘴山市| 阿拉善盟| 南郑县| 类乌齐县| 呈贡县| 舞钢市| 子洲县| 井冈山市| 海安县| 北宁市| 屯昌县| 漠河县| 徐闻县| 南皮县| 十堰市| 石渠县| 怀柔区| 邵阳市| 敦化市| 会宁县| 临安市| 芒康县| 图们市| 临颍县| 峨眉山市| 阜新市| 文成县| 樟树市| 江川县|