项目中经常遇到需要一对多的列表,如果想省事,可以直接正常的返回list列表后交给前端处理,但这种处理前端也挺惨的,所有直接一对多关系的列表还是很nice的.一下记录下以前自己用到的几种方法.
1.在java代码中处理
public IPage<Map<String,Object>> xxxxList(Page<Map<String,Object>> page, String year) {
List<Map<String, Object>> retList = new ArrayList<>();
List<Map<String, Object>> mapList = this.baseMapper.xxxxList(year);
for (Map<String, Object> map: mapList){
List<Map<String, Object>> list = this.baseMapper.ccccList(map);
Map<String, Object> retMap = new HashMap<>();
retMap.put("year",map.get("year"));
retMap.put("taskName",map.get("taskName"));
retMap.put("taskId",map.get("taskId"));
retMap.put("children",list);
retList.add(retMap);
}
page.setRecords(retList);
page.setTotal(retList.size());
return page;
}
这是代码层面处理的一对多关系,通过主从两次查询加入到集合中,且在加入分页后一般不会出现总数与列表有偏差的情况,结果是这种格式:
{
{
"taskId":"",
"taskName":"",
"year":"",
"children": [
{
"Id": "string",
"param": "string",
"paramName": "string",
"score": "string"
},
{
"Id": "string",
"param": "string",
"paramName": "string",
"score": "string"
},
{
"Id": "string",
"param": "string",
"paramName": "string",
"score": "string"
}
]
}
}
当然作为开发者能一步搞定的问题绝不繁琐着来,相对于mybatis一次查出,java层遍历会消耗更多资源,于是第二种通过一次查询来完成一对多的方法如下:
2.在mybatis中关联查询
<resultMap id="BaseResultMap" type="map">
<result column="task_id" jdbcType="VARCHAR" property="taskId"/>
<result column="task_name" jdbcType="VARCHAR" property="taskName"/>
<result column="year" jdbcType="INTEGER" property="year"/>
<collection property="children" column="{taskId=task_id,year=year}" select="xxxxList1">
</collection>
</resultMap>
<select id="xxxxxList" parameterType="java.lang.String" resultMap="BaseResultMap">
SELECT
t.year,
t.task_id,
t.task_name
FROM
taskin t
WHERE t.assign_score = '1'
<if test="year != null and year != ''">
AND t.year = #{year}
</if>
GROUP BY t.task_id
ORDER BY IFNULL (t.update_time, t.create_time) DESC
</select>
<select id="xxxxList1" parameterType="map" resultType="map">
SELECT
t.id,
t.task_id,
t.task_name,
t.param,
t.param_name,
t.score
FROM
taskin t
WHERE t.an_score = '1'
AND t.year = #{year}
<if test="taskId != null and taskId != ''">
AND t.task_id = #{taskId}
</if>
</select>
其中column="{taskId=task_id,year=year}" taskId是随便命名的字段,task_id查询的字段,两字段要与子母sql相对应,以实现多参数传入子sql,此sql查询的结果就是一对多,并可把结果进行分页处理.
当然常见的collection格式可以这样写
<collection property="children" column="id" ofType="map">
<result column="id" property="id"/>
<result column="param" property="param"/>
<result column="param_name" property="paramName"/>
<result column="score" property="score"/>
</collection>
这个写法很常见,有一点目前踩过的坑就是采用分页调用该形式,列表总数和列表条数对不上的情况,而且此情况一般测试不易被发觉,只有系统上线后或者综合测试时才会看出.也有可能自己没深入研究此种解决方法的原因.
以上是一对多的几种形式,如果大家有更好的方法来处理请留言相互探讨!