背景 考慮以下場景: InfoTable(信息表): | Name | Gender | Age | Score | | | | | | | 張三 | 男 | 21 | 90 | | 李四 | 女 | 20 | 87 | | 王五 | 男 | 22 | 92 | | 趙六 | 女 | 19 | 94 ...
背景
考慮以下場景:
InfoTable(信息表):
Name | Gender | Age | Score |
---|---|---|---|
張三 | 男 | 21 | 90 |
李四 | 女 | 20 | 87 |
王五 | 男 | 22 | 92 |
趙六 | 女 | 19 | 94 |
孫七 | 女 | 23 | 88 |
周八 | 男 | 20 | 91 |
StatusTable(狀態表,指是否有在考試之前複習):
Name | hasReview |
---|---|
張三 | 是 |
李四 | 否 |
王五 | 是 |
趙六 | 是 |
孫七 | 否 |
周八 | 是 |
現在,我想知道所有複習過的學生的成績,可以利用mysql中的子查詢來實現:
SELECT Score
FROM InfoTable
WHERE Name in (SELECT Name
FROM StatusTable
WHERE hasReview = '是');
這種方式非常方便,我們只要把查詢條件寫出來,剩下的操作都由mysql來處理。而在實際場景中,為了減少底層耦合,我們一般不通過mysql中的子查詢方式聯表查詢,而是先執行子查詢得到結果集,再以結果集作為條件執行外層查詢。通常情況下,子查詢和外層查詢由上層的不同服務執行,這樣就在一定程度上達到了底層資料庫解耦的目的。註意這種實現方式將mysql內部的一部分複雜操作拋給了我們。這時,Mybatis中的foreach
標簽就有了用武之地。
Mybatis 中foreach
標簽的用法
還以剛纔的例子來說,先執行子查詢
SELECT Name FROM StatusTable WHERE hasReview = '是'
再執行外層查詢,就是
SELECT Score
FROM InfoTable
WHERE Name in ('張三' , '王五', '趙六', '周八');
也就是一個批量查詢操作,將其抽象一下(假設有三個條件):
SELECT *
FROM <tableName>
WHERE <ColumnName> IN (<case1>,<case2>,<case3>)
實際情況中,case可能遠不止3個,這時可以在XXXMapper.xml文件中利用Mybatis中的foreach
編寫sql語句:
SELECT *
FROM <tableName>
WHERE <ColumnName> IN
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
就可以實現相同的效果了。
那麼問題來了,foreach
標簽中各種參數是什麼含義呢?
- collection
- 如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list
- 如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array
- 如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map,實際上如果你在傳入參數的時候,在breast裡面也是會把它封裝成一個Map的,map的key就是參數名,所以這個時候collection屬性值就是傳入的List或array對象在自己封裝的map裡面的key
- index 集合迭代位置
- item 集合中的每一個元素別名
- open 開始符號,例如這裡的
(
,就對應於IN (<case1>,<case2>,<case3>)
中IN後面的第一個(
- separator 分隔符,例如這裡的
,
,就對應於IN (<case1>,<case2>,<case3>)
中的,
- close 結束符號,例如這裡的
)
,就對應於IN (<case1>,<case2>,<case3>)
中<case3>
後面的)
參考
Mybatis中
屬性的含義 之 collection1.eg:
<select id="getEmpsInNames" resultType="emp"> select * from emp where ename in <foreach collection="list" index="index" item="name" open="(" separator="," close=")"> #{name} </foreach> </select>
對應的測試代碼:
@Test public void dynamicForeachTest() { SqlSession session = Util.getSqlSessionFactory().openSession(); BlogMapper blogMapper = session.getMapper(BlogMapper.class); List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(3); ids.add(6); List<Blog> blogs = blogMapper.dynamicForeachTest(ids); for (Blog blog : blogs) System.out.println(blog); session.close(); }
2.eg:
<select id="dynamicForeach2Test" resultType="Blog"> select * from t_blog where id in <foreach collection="array" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </select>
對應的測試代碼:
@Test public void dynamicForeach2Test() { SqlSession session = Util.getSqlSessionFactory().openSession(); BlogMapper blogMapper = session.getMapper(BlogMapper.class); int[] ids = new int[] {1,3,6,9}; List<Blog> blogs = blogMapper.dynamicForeach2Test(ids); for (Blog blog : blogs) System.out.println(blog); session.close(); }
3.eg:
自己把參數封裝成Map的類型
<select id="dynamicForeach3Test" 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 ListdynamicForeach3Test(Map<String, Object> params);
對應測試代碼:@Test public void dynamicForeach3Test() { SqlSession session = Util.getSqlSessionFactory().openSession(); BlogMapper blogMapper = session.getMapper(BlogMapper.class); final List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); ids.add(3); ids.add(6); ids.add(7); ids.add(9); Map<String, Object> params = new HashMap<String, Object>(); params.put("ids", ids); params.put("title", "中國"); List<Blog> blogs = blogMapper.dynamicForeach3Test(params); for (Blog blog : blogs) System.out.println(blog); session.close(); }