這篇文章將為大家詳細(xì)講解有關(guān)foreach怎么在mybatis中使用,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
成都創(chuàng)新互聯(lián)堅(jiān)信:善待客戶(hù),將會(huì)成為終身客戶(hù)。我們能堅(jiān)持多年,是因?yàn)槲覀円恢笨芍档眯刨?lài)。我們從不忽悠初訪客戶(hù),我們用心做好本職工作,不忘初心,方得始終。十余年網(wǎng)站建設(shè)經(jīng)驗(yàn)成都創(chuàng)新互聯(lián)是成都老牌網(wǎng)站營(yíng)銷(xiāo)服務(wù)商,為您提供成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、H5建站、網(wǎng)站制作、成都品牌網(wǎng)站建設(shè)、微信小程序服務(wù),給眾多知名企業(yè)提供過(guò)好品質(zhì)的建站服務(wù)。foreach元素的屬性主要有item,index,collection,open,separator,close。
item:集合中元素迭代時(shí)的別名,該參數(shù)為必選。
index:在list和數(shù)組中,index是元素的序號(hào),在map中,index是元素的key,該參數(shù)可選
open:foreach代碼的開(kāi)始符號(hào),一般是(和close=")"合用。常用在in(),values()時(shí)。該參數(shù)可選
separator:元素之間的分隔符,例如在in()的時(shí)候,separator=","會(huì)自動(dòng)在元素中間用“,“隔開(kāi),避免手動(dòng)輸入逗號(hào)導(dǎo)致sql錯(cuò)誤,如in(1,2,)這樣。該參數(shù)可選。
close: foreach代碼的關(guān)閉符號(hào),一般是)和open="("合用。常用在in(),values()時(shí)。該參數(shù)可選。
collection: 要做foreach的對(duì)象,作為入?yún)r(shí),List對(duì)象默認(rèn)用"list"代替作為鍵,數(shù)組對(duì)象有"array"代替作為鍵,Map對(duì)象沒(méi)有默認(rèn)的鍵。當(dāng)然在作為入?yún)r(shí)可以使用@Param("keyName")來(lái)設(shè)置鍵,設(shè)置keyName后,list,array將會(huì)失效。 除了入?yún)⑦@種情況外,還有一種作為參數(shù)對(duì)象的某個(gè)字段的時(shí)候。舉個(gè)例子:如果User有屬性List ids。入?yún)⑹荱ser對(duì)象,那么這個(gè)collection = "ids".如果User有屬性Ids ids;其中Ids是個(gè)對(duì)象,Ids有個(gè)屬性List id;入?yún)⑹荱ser對(duì)象,那么collection = "ids.id"
在使用foreach的時(shí)候最關(guān)鍵的也是最容易出錯(cuò)的就是collection屬性,該屬性是必須指定的,但是在不同情況下,該屬性的值是不一樣的,主要有一下3種情況:
如果傳入的是單參數(shù)且參數(shù)類(lèi)型是一個(gè)List的時(shí)候,collection屬性值為list .
如果傳入的是單參數(shù)且參數(shù)類(lèi)型是一個(gè)array數(shù)組的時(shí)候,collection的屬性值為array .
如果傳入的參數(shù)是多個(gè)的時(shí)候,我們就需要把它們封裝成一個(gè)Map了,當(dāng)然單參數(shù)也可以封裝成map,實(shí)際上如果你在傳入?yún)?shù)的時(shí)候,在MyBatis里面也是會(huì)把它封裝成一個(gè)Map的,map的key就是參數(shù)名,所以這個(gè)時(shí)候collection屬性值就是傳入的List或array對(duì)象在自己封裝的map里面的key.
針對(duì)最后一條,我們來(lái)看一下官方說(shuō)法:
注意 你可以將一個(gè) List 實(shí)例或者數(shù)組作為參數(shù)對(duì)象傳給 MyBatis,當(dāng)你這么做的時(shí)候,MyBatis 會(huì)自動(dòng)將它包裝在一個(gè) Map 中并以名稱(chēng)為鍵。List 實(shí)例將會(huì)以“l(fā)ist”作為鍵,而數(shù)組實(shí)例的鍵將是“array”。
所以,不管是多參數(shù)還是單參數(shù)的list,array類(lèi)型,都可以封裝為map進(jìn)行傳遞。如果傳遞的是一個(gè)List,則mybatis會(huì)封裝為一個(gè)list為key,list值為object的map,如果是array,則封裝成一個(gè)array為key,array的值為object的map,如果自己封裝呢,則colloection里放的是自己封裝的map里的key值。
源碼分析
由于官方文檔對(duì)這塊的使用,描述的比較簡(jiǎn)短,細(xì)節(jié)上也被忽略掉了(可能是開(kāi)源項(xiàng)目文檔一貫的問(wèn)題吧),也使用不少同學(xué)在使用中遇到了問(wèn)題。特別是foreach這個(gè)函數(shù)中,collection屬性做什么用,有什么注意事項(xiàng)。由于文檔不全,這塊只能通過(guò)源代碼剖析的方式來(lái)分析一下各個(gè)屬性的相關(guān)要求。
collection屬性的用途是接收輸入的數(shù)組或是List接口實(shí)現(xiàn)。但對(duì)于其名稱(chēng)的要求,Mybatis在實(shí)現(xiàn)中還是有點(diǎn)不好理解的,所以需要特別注意這一點(diǎn)。
下面開(kāi)始分析源代碼(筆記使用的是Mybatis 3.0.5版本)
先找到Mybatis執(zhí)行SQL配置解析的入口
MapperMethod.java類(lèi)中publicObject execute(Object[] args)該方法是執(zhí)行的入口.
針對(duì)in集合查詢(xún),對(duì)應(yīng)用就是selectForList或SelctForMap方法。
但不管調(diào)用哪個(gè)方法,都會(huì)對(duì)原來(lái)JDK傳入的參數(shù) Object[]類(lèi)型,通過(guò) getParam方法轉(zhuǎn)換成一個(gè)Object,那這個(gè)方法是做什么的呢?分析源碼如下:
上圖中標(biāo)紅的兩處,很驚訝的發(fā)現(xiàn),一個(gè)參數(shù)與多個(gè)參數(shù)的處理方式是不同的(后續(xù)很多同學(xué)遇到的問(wèn)題,就有一大部分出自這個(gè)地方)。如果參數(shù)個(gè)數(shù)大于一個(gè),則會(huì)被封裝成Map, key值如果使用了Mybatis的 Param注解,則會(huì)使用該key值,否則默認(rèn)統(tǒng)一使用數(shù)據(jù)序號(hào),從1開(kāi)始。這個(gè)問(wèn)題先記下,繼續(xù)分析代碼,接下來(lái)如果是selectForList操作(其它操作就對(duì)應(yīng)用相應(yīng)方法),會(huì)調(diào)用DefaultSqlSession的publicListselectList(String statement, Object parameter, RowBounds rowBounds)方法
又一個(gè)發(fā)現(xiàn),見(jiàn)源代碼如下:
上圖標(biāo)紅部分,對(duì)參數(shù)又做了一次封裝,我們看一下代碼
現(xiàn)在有點(diǎn)清楚了,如果參數(shù)類(lèi)型是List,則必須在collecion中指定為list, 如果是數(shù)據(jù)組,則必須在collection屬性中指定為 array.
現(xiàn)在就問(wèn)題就比較清楚了,如果是一個(gè)參數(shù)的話,collection的值取決于你的參數(shù)類(lèi)型。
如果是多個(gè)值的話,除非使用注解Param指定,否則都是數(shù)字開(kāi)頭,所以在collection中指定什么值都是無(wú)用的。下圖是debug顯示結(jié)果。
使用方法
單參數(shù)List 類(lèi)型
測(cè)試代碼:
@Test public void shouldHandleComplexNullItem() { SqlSession sqlSession = sqlSessionFactory.openSession(); try { Mapper mapper = sqlSession.getMapper(Mapper.class); User user1 = new User(); user1.setId(2); user1.setName("User2"); Listusers = new ArrayList (); users.add(user1); users.add(null); int count = mapper.countByUserList(users); Assert.assertEquals(1, count); } finally { sqlSession.close(); } }
上述collection為array,對(duì)應(yīng)的Mapper代碼:
public List dynamicForeach3Test(int[] ids);
對(duì)應(yīng)的測(cè)試代碼:
@Test public void dynamicForeach3Test() { SqlSession session = Util.getSqlSessionFactory().openSession(); BlogMapper blogMapper = session.getMapper(BlogMapper.class); int[] ids = new int[] {1,3,6,9}; List blogs = blogMapper.dynamicForeach3Test(ids); for (Blog blog : blogs) System.out.println(blog); session.close(); }
3.自己把參數(shù)封裝成Map的類(lèi)型
上述collection的值為ids,是傳入的參數(shù)Map的key,對(duì)應(yīng)的Mapper代碼:
public List dynamicForeach4Test(Map params);
對(duì)應(yīng)測(cè)試代碼:
@Test public void dynamicForeach4Test() { SqlSession session = Util.getSqlSessionFactory().openSession(); BlogMapper blogMapper = session.getMapper(BlogMapper.class); final List ids = new ArrayList(); ids.add(1); ids.add(2); ids.add(3); ids.add(6); ids.add(7); ids.add(9); Map params = new HashMap(); params.put("ids", ids); params.put("title", "中國(guó)"); List blogs = blogMapper.dynamicForeach4Test(params); for (Blog blog : blogs) System.out.println(blog); session.close(); }
關(guān)于foreach怎么在mybatis中使用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。