背景
考虑以下场景:
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. 文件中利用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中属性的含义 之 collection
1.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 like \"%\"#{ }\"%\" and id in <foreach collection=\"ids\" index=\"index\" item=\"item\" open=\"(\" separator=\",\" close=\")\"> #{item} </foreach> </select>上述collection的值为ids,是传入的参数Map的key,对应的Mapper代码:
public List dynamicForeach3Test(Map<String, > 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, > params = new HashMap<String, >(); params.put(\"ids\", ids); params.put(\" \", \"中国\"); List<Blog> blogs = blogMapper.dynamicForeach3Test(params); for (Blog blog : blogs) System.out.println(blog); session.close(); }
继续阅读与本文标签相同的文章
-
字节跳动要做一款24小时在家陪读的AI教练,原锤子团队参与研发
2026-05-18栏目: 教程
-
全能扫描工具,支持OCR文字识别,全平台
2026-05-18栏目: 教程
-
区块链国家队来了!国家信息中心与银联等联合发布区块链服务网
2026-05-18栏目: 教程
-
什么是企业部署物联网的重点?
2026-05-18栏目: 教程
-
法大大创始人兼CEO黄翔:中国电子签名市场渗透率不到1% 复合增长率可达200%
2026-05-18栏目: 教程
