一、需求背景
一条银行产品的需求,不同阶段,可能对应不同的银行(也有可能是同一个银行处理不同的阶段)去处理,如:
发布
阶段: —>A银行
处理立项
阶段: —> B银行处理审核
阶段: —>A银行
处理出账
阶段: —> C银行处理
在查询这条需求的时候,需要将这些阶段的处理记录连带查询出来,放在一个List里面。我们常用的方法就是使用 LEFT JOIN
关联查询,然后使用 collection
标签收集组合,事实上我就是使用这种方法去处理的,collection
标签大致如下:
<resultMap id="businessProcessRecordMap" type="XXXRecordVO" autoMapping="true">
<id property="demandNo" column="demandNo"/>
<collection property="bankList" notNullColumn="bankId" javaType="java.util.List" autoMapping="true" ofType="XXXRecordVO$Bank">
<id property="id" column="bankId"/>
<result column="bankName" property="name"/>
<result column="operateDate" property="operateDate"/>
<result column="status" property="status"/>
</collection>
</resultMap>
二、问题
现在的问题就是: 如果同一家银行处理了不同阶段
,那么返回的结果也只有一条记录,即:同一家银行的数据
被Mybatis的connection标签自动去重了
,显然这个去重规则是不满足我们的要求的;因此我们需要特殊处理一下;
mybatis collection设计的原则就是去重聚合,其去重大致原理就是根据collection标签中的<id>
标签去重的。因此,我们就会发现导致错误去重的根本原因就是:同一家银行处理多个阶段的数据时,银行的id是一样的
,即<id property="id" column="bankId"/>
是一样的,这就导致Mybatis错误去重了,知道问题的根本所在,我们就可以对症下药了:
三、解决办法
知道问题产生的原因之后,我们可以从sql查询语句入手:
SELECT
man.demand_no AS demandNo,
bkser.`name` AS bankName,
bkser.id AS bankId,
cess.create_time AS operateDate,
cess.node AS `status`,
# 拼接银行id和当前处理记录的状态,解决collection去重问题
CONCAT(bkser.id,cess.node) AS nodeIdStr
FROM
如上,我们拼接了一个银行id+当前节点状态
作为一个查询列,然后,在collection中,我们做出如下改造:
<resultMap id="businessProcessRecordMap" type="XXXRecordVO" autoMapping="true">
<id property="demandNo" column="demandNo"/>
<collection property="bankList" notNullColumn="bankId" javaType="java.util.List" autoMapping="true" ofType="XXXRecordVO$Bank">
# 指定collection的id为nodeIdStr,这样,Mybatis在去重的时候,就会根据这个列去重,这样就能满足我们的去重需求了;
# 这样指定,并不会影响我们的bankList返回结果
<id property="id" column="nodeIdStr"/>
<result property="id" column="bankId"/>
<result column="bankName" property="name"/>
<result column="operateDate" property="operateDate"/>
<result column="status" property="status"/>
</collection>
</resultMap>
经过如上改造,Mybatis的自动去重已经满足我们的需求了,并且,这样的改造并没有影响最终的bankList返回结果,结果如下: