mybatis双重foreach如何实现遍历map中的两个list数组
作者:flytalei
实现背景
前端传值时可能会有多个字段传递过来,需要后台将这多个字段拼接为 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期"]}]
Debug断点调试java如何解析json对象
综上所述,后台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.fromObject()
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
由第一步可以看出此时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
此时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>
foreach标签说明
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} inopen
:in语句循环开始的符号,我们知道sql中in后面的条件是用()括起来的,所以这里我们填写的属性是open="("close
:in语句循环结束的符号,同上,有开始就有结束,所以这里我们填写的属性是close=")"separator
:多个条件拼接时的分隔符,我们知道in语句中会有多个条件即in(1,2,3,4)而多个条件使用逗号分割,所以这里我们填写的属性是separator=","
最终效果
最后由控制台可以看出,我们已经成功拼接了and xxx in (?,?,?)
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。