中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

mybatis中foreach如何使用

發布時間:2021-07-10 17:36:22 來源:億速云 閱讀:153 作者:Leah 欄目:編程語言

mybatis中foreach如何使用,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

在做mybatis的mapper.xml文件的時候,我們時常用到這樣的情況:動態生成sql語句的查詢條件,這個時候我們就可以用mybatis的foreach了

foreach元素的屬性主要有item,index,collection,open,separator,close。

item:集合中元素迭代時的別名,該參數為必選。  index:在list和數組中,index是元素的序號,在map中,index是元素的key,該參數可選  open:foreach代碼的開始符號,一般是(和close=")"合用。常用在in(),values()時。該參數可選  separator:元素之間的分隔符,例如在in()的時候,separator=","會自動在元素中間用“,“隔開,避免手動輸入逗號導致sql錯誤,如in(1,2,)這樣。該參數可選。  close: foreach代碼的關閉符號,一般是)和open="("合用。常用在in(),values()時。該參數可選。  collection: 要做foreach的對象,作為入參時,List對象默認用"list"代替作為鍵,數組對象有"array"代替作為鍵,Map對象沒有默認的鍵。當然在作為入參時可以使用@Param("keyName")來設置鍵,設置keyName后,list,array將會失效。 除了入參這種情況外,還有一種作為參數對象的某個字段的時候。舉個例子:如果User有屬性List ids。入參是User對象,那么這個collection = "ids".如果User有屬性Ids ids;其中Ids是個對象,Ids有個屬性List id;入參是User對象,那么collection = "ids.id"

在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況下,該屬性的值是不一樣的,主要有一下3種情況:

如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list .  如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array .  如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map,實際上如果你在傳入參數的時候,在MyBatis里面也是會把它封裝成一個Map的,map的key就是參數名,所以這個時候collection屬性值就是傳入的List或array對象在自己封裝的map里面的key.

針對最后一條,我們來看一下官方說法:

注意 你可以將一個 List 實例或者數組作為參數對象傳給 MyBatis,當你這么做的時候,MyBatis 會自動將它包裝在一個 Map 中并以名稱為鍵。List 實例將會以“list”作為鍵,而數組實例的鍵將是“array”。

所以,不管是多參數還是單參數的list,array類型,都可以封裝為map進行傳遞。如果傳遞的是一個List,則mybatis會封裝為一個list為key,list值為object的map,如果是array,則封裝成一個array為key,array的值為object的map,如果自己封裝呢,則colloection里放的是自己封裝的map里的key值。

源碼分析

由于官方文檔對這塊的使用,描述的比較簡短,細節上也被忽略掉了(可能是開源項目文檔一貫的問題吧),也使用不少同學在使用中遇到了問題。特別是foreach這個函數中,collection屬性做什么用,有什么注意事項。由于文檔不全,這塊只能通過源代碼剖析的方式來分析一下各個屬性的相關要求。

collection屬性的用途是接收輸入的數組或是List接口實現。但對于其名稱的要求,Mybatis在實現中還是有點不好理解的,所以需要特別注意這一點。

下面開始分析源代碼(筆記使用的是Mybatis 3.0.5版本)

先找到Mybatis執行SQL配置解析的入口

MapperMethod.java類中publicObject execute(Object[] args)該方法是執行的入口.

針對in集合查詢,對應用就是selectForList或SelctForMap方法。

但不管調用哪個方法,都會對原來JDK傳入的參數 Object[]類型,通過 getParam方法轉換成一個Object,那這個方法是做什么的呢?分析源碼如下:

上圖中標紅的兩處,很驚訝的發現,一個參數與多個參數的處理方式是不同的(后續很多同學遇到的問題,就有一大部分出自這個地方)。如果參數個數大于一個,則會被封裝成Map, key值如果使用了Mybatis的 Param注解,則會使用該key值,否則默認統一使用數據序號,從1開始。這個問題先記下,繼續分析代碼,接下來如果是selectForList操作(其它操作就對應用相應方法),會調用DefaultSqlSession的publicListselectList(String statement, Object parameter, RowBounds rowBounds)方法

又一個發現,見源代碼如下:

上圖標紅部分,對參數又做了一次封裝,我們看一下代碼

現在有點清楚了,如果參數類型是List,則必須在collecion中指定為list, 如果是數據組,則必須在collection屬性中指定為 array.

現在就問題就比較清楚了,如果是一個參數的話,collection的值取決于你的參數類型。

如果是多個值的話,除非使用注解Param指定,否則都是數字開頭,所以在collection中指定什么值都是無用的。下圖是debug顯示結果。

使用方法

單參數List 類型

<select id="countByUserList" resultType="_int" parameterType="list">select count(*) from users <where>  id in  <foreach item="item" collection="list" separator="," open="(" close=")" index="">   #{item.id, jdbcType=NUMERIC}  </foreach> </where></select>

測試代碼:

@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");   List<User> users = new ArrayList<User>();   users.add(user1);   users.add(null);   int count = mapper.countByUserList(users);   Assert.assertEquals(1, count);  } finally {   sqlSession.close();  } }

上述collection為array,對應的Mapper代碼:

public List dynamicForeach3Test(int[] ids);

對應的測試代碼:

@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.自己把參數封裝成Map的類型

<select id="dynamicForeach4Test" resultType="Blog">     select * from t_blog where title like "%"#{title}"%" and id in     <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">        #{item}     </foreach> </select>

上述collection的值為ids,是傳入的參數Map的key,對應的Mapper代碼:

public List dynamicForeach4Test(Map params);

對應測試代碼:

@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", "中國");    List blogs = blogMapper.dynamicForeach4Test(params);     for (Blog blog : blogs)       System.out.println(blog);     session.close();   }

注意注意sql語句SELECT * FROM ny_jobs WHERE id IN () 這個會報錯,所以最后判斷一下Ids是有元素的

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

德庆县| 依兰县| 兴山县| 荥阳市| 江陵县| 清涧县| 甘谷县| 防城港市| 宜城市| 九江市| 孟村| 高邮市| 类乌齐县| 盐边县| 满洲里市| 华蓥市| 疏附县| 浮梁县| 长沙市| 普宁市| 万源市| 方正县| 友谊县| 延庆县| 大洼县| 太仆寺旗| 北安市| 樟树市| 万安县| 南召县| 抚顺市| 卓尼县| 刚察县| 建阳市| 镇赉县| 舟山市| 化隆| 舟曲县| 安乡县| 宁城县| 华容县|