前端传值时可能会有多个字段传递过来,需要后台将这多个字段拼接为 name in (? , ?) and name1 in (? , ?) and name2 in (? , ?) 作为sql查询条件…如下图sql语句,即实现多个and xxx in(?,?,?) 拼接
select * from web_ztlc_provateequity WHERE
cords in ( ? , ? , ? )
and productName in ( ? , ? , ? )
and product_id in ( ? , ? , ? )
前端传递的是json字符串,json中name和infos是一对具有对应关系的对象,且json中会有多条这种对象,即此对象是一个数组。而infos中也会有多条数据,即infos也是一个数组对象。所以最终前端传递过来json格式如下
json字符串:
itemList:[{"name":"cords", "infos":["2", "2222", "2223","2224","2225","2226"] },
{"name":"productName", "infos":["2号B","SAP智龙3号私募证券投资基金","一村金衍10号第1期"]}]
综上所述,后台Java接口在获取到json字符串后,需要遍历json中的两个数组对象,即name和infos
//模拟数据测试前端传参
String itemList="[{ \"name\":\"cords\", \"infos\":[ \"2\", \"2222\", \"2223\",\"2224\",\"2225\",\"2226\" ] },{ \"name\":\"productName\", \"infos\":[ \"2号B\",\"SAP智龙3号私募证券投资基金\",\"一村金衍10号第1期\" ] }]";
//获取前端传过来的参数数组
//String itemList = request.getParameter("itemList");
if(!StringUtils.isEmpty(itemList)){
//将参数数组转化为json数组类型
JSONArray jsonArray = JSONArray.fromObject(itemList);
if(jsonArray.size()!=0){
Map<String,Object> columnMap = new HashMap<>();
//遍历jsonarray数组
for(int i = 0;i < jsonArray.size(); i++) {
net.sf.json.JSONObject job = jsonArray.getJSONObject(i);
String name = job.getString("name");
List<String> lists =job.getJSONArray("infos");
if(lists.size()!= 0){
columnMap.put(name,lists);
}
}
hm.put("columnMap",columnMap);
}else{
return null;
}
}
JSONArray jsonArray = JSONArray.fromObject(itemList);
从上图可以看出JSONArray.fromObject(itemList)后,jsonArray已经size=2(解析出了两条json对象,每条对象又由name和infos各自的键值对(key =>value)组成,name中name为key,cords为value(这里的cords就是后面我们sql语句中需要拼接的and条件的字段值);infos中的key为infos,而value又是一个数组对象(这个数组里的各个对象,就是我们后面sql语句中需要拼接的in的条件))
由第一步可以看出此时jsonArray里已经存放了数组下标为0和1的两条数据,那么此时我们就挨个的取出这两条数据(也就是遍历啦)
第一次for循环0数组,取出0数组中的name和infos,可以看出我们声明了一个lists数组,由来存放infos中的所以数值
如下图,我们同时还声明了一个columnMap的Map对象,此对象用来存储从json中获取到的name和infos。将name和infos封装成键值对(key=>value)的Map对象,将来传递给Mybatis的parameterType="hashmap"的入参属性,通过key来找value。
每次for循环就放一个键值对对象进columnMap,我们这里测试数据只有两条,所以columnMap最终会被放进两个键值对对象即columnMap的size=2.
此时mybatis双重foreach的雏形就出来了,因为columnMap中已经有2个key=>value对象了。也就意味着有多个key,而每个key又对应多个value。所以此时mybais的foreach循环就得嵌套,第一次循环key,循环key时又得循环key对应的多个value
最终需要foreach双重遍历的Map集合的数据结构
columnMap为key的value中又存在多个key/value对象,columnMap的结构如下
<select id="queryAllWebZtlcProvateequity" resultMap="BaseResultMap" parameterType="hashmap">
select * from web_ztlc_provateequity
<where>
<if test="columnMap != null and columnMap !=''">
<foreach item="item" collection="columnMap.entrySet()" index="key" >
and ${key} in
<foreach item="value" collection="item" open="(" close=")" separator=",">
#{value}
foreach>
foreach>
if>
where>
select>
collection:需要遍历的对象,以上代码可以看出我写的是collection="columnMap.entrySet()",columnMap是我封装的Map对象,而entrySet()则是Map的内置方法,存储的是Map中的键值对集合,此时第一个foreach就是在遍历Map中的key。
item:遍历时每个元素遍历出来时的别名,这个别名有用,我们第二次foreach是会用到,因为第一次foreach的是key集合,那么第二次foreach时就得遍历key对应的value集合。
index:表示索引,也就是遍历集合中的数组下标,0,1,2,3......等,可以看出这里我填写的标签属性是index="key",下面and拼接时取得就是$key这个变量and ${key} in
open:in语句循环开始的符号,我们知道sql中in后面的条件是用()括起来的,所以这里我们填写的属性是open="("
close:in语句循环结束的符号,同上,有开始就有结束,所以这里我们填写的属性是close=")"
separator:多个条件拼接时的分隔符,我们知道in语句中会有多个条件即in(1,2,3,4)而多个条件使用逗号分割,所以这里我们填写的属性是separator=","