Mybatis foreach标签含义
背景
考虑以下场景:
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,实际上如果你在传入参数的时候,在里面也是会把它封装成一个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(); }
推荐阅读