一、问题描述
最近在做项目时,需要使用Mybatis的ResultMap高级映射查询“校区 - 楼栋 - 楼层”树结构的数据,前端提供很多过滤条件都是子查询楼层的一些字段属性,并不是所有的参数都是最外层查询的过滤条件,但是ResultMap本身不支持将参数从外层的查询一直传递到子查询。
举个简单的例子,mapper接口传递了一些参数到mapper.xml中,如果不额外处理,这些参数只能在最外面一层resultMap对应的sql中获取到进行使用,那么很多情况下我们是resultMap下面还包含了collection子查询,子查询也用到这些过滤条件,本文总结的就是如何将参数一直传递到最后面一层查询。
二、解决方法
在外层查询的时候,将参数作为返回结果的一列放在sql中,使用resultMap的collection的column列传递参数时一并将我们构造的假的结果列传递过去,这样子查询就可以使用到外层传递的参数,以此类推,不管有多少层嵌套查询,最外层的参数都可以一直传递到最下面一层查询。具体见代码:
【a】Mapper.java接口
public List getCwTreeDataSource(@Param("xqids") String xqidFilterStr, @Param("ldids") String ldidFilterStr,
@Param("filterParamMap") Map filterParamMap);
【b】Mapper.xml完整代码:通过ResultMap查询树结构数据 "校区 - 楼栋 - 楼层"
select r.*,
case
when '${ldids}' IS NULL then
NULL
else
'${ldids}'
end as ldids,
case
when '${filterParamMap.cyid}' IS NULL then
NULL
else
'${filterParamMap.cyid}'
end as cyid,
case
when '${filterParamMap.type}' IS NULL then
NULL
else
'${filterParamMap.type}'
end as type,
case
when '${filterParamMap.ssnj}' IS NULL then
NULL
else
'${filterParamMap.ssnj}'
end as ssnj,
'xq' as cj,
r.label as title
from (select distinct t1.XQID as value,
t1.XQMC as label,
t1.PXH,
nvl(sum(case
when (t6.rzzt = '2' or t6.rzzt = '1') then
1
else
0
end),
0) as yrzcws,
nvl(count(t5.pkid), 0) as zcws
from vc_zhxg_xtgl_jcsj_xqxx t1
left join zhxg_gy_jcsj_ldxx t2
on t2.xqid = t1.XQID
left join zhxg_gy_jcsj_lcxx t3
on t2.pkid = t3.ldid
left join zhxg_gy_jcsj_fjxx t4
on t3.pkid = t4.lcid
left join zhxg_gy_jcsj_cwxx t5
on t4.pkid = t5.fjid
left join zhxg_gy_ssfp_cwfp t6
on t6.cwid = t5.pkid
where 1 = 1
and t6.bjid in
#{item}
and t6.zyid in
#{item}
and t6.bmid in
#{item}
and t6.nj in
#{item}
and t1.XQID in
#{xqid}
group by t1.XQID, t1.XQMC, t1.PXH) r
order by r.pxh
select r.*,
case
when '${cyid}' IS NULL then
NULL
else
'${cyid}'
end as cyid,
case
when '${type}' IS NULL then
NULL
else
'${type}'
end as type,
case
when '${ssnj}' IS NULL then
NULL
else
'${ssnj}'
end as ssnj,
'ld' as cj,
r.xqmc || ' - ' || r.label as title
from (select t1.pkid as value,
t1.ldmc as label,
t1.pxh,
nvl(sum(case
when (t5.rzzt = '2' or t5.rzzt = '1') then
1
else
0
end),
0) as yrzcws,
nvl(count(t4.pkid), 0) as zcws,
t6.XQMC
from zhxg_gy_jcsj_ldxx t1
left join vc_zhxg_xtgl_jcsj_xqxx t6
on t1.xqid = t6.XQID
left join zhxg_gy_jcsj_lcxx t2
on t1.pkid = t2.ldid
left join zhxg_gy_jcsj_fjxx t3
on t2.pkid = t3.lcid
left join zhxg_gy_jcsj_cwxx t4
on t3.pkid = t4.fjid
left join zhxg_gy_ssfp_cwfp t5
on t4.pkid = t5.cwid
where 1 = 1
and t1.xqid = #{value}
and t5.bjid in
#{item}
and t5.zyid in
#{item}
and t5.bmid in
#{item}
and t5.nj in
#{item}
and t1.pkid in
#{ldid}
group by t1.pkid, t1.ldmc, t1.pxh,t6.XQMC) r
order by r.pxh
select t1.pkid as value,
t1.lcmc as label,
t1.pxh,
nvl(sum(case
when (t5.rzzt = '2' or t5.rzzt = '1') then
1
else
0
end),
0) as yrzcws,
nvl(count(t4.pkid), 0) as zcws,
'lc' as cj,
t6.XQMC || ' - ' || t2.ldmc || ' - ' || t1.lcmc as title
from zhxg_gy_jcsj_lcxx t1
left join zhxg_gy_jcsj_ldxx t2
on t1.ldid = t2.pkid
left join vc_zhxg_xtgl_jcsj_xqxx t6
on t2.xqid = t6.XQID
left join zhxg_gy_jcsj_fjxx t3
on t1.pkid = t3.lcid
left join zhxg_gy_jcsj_cwxx t4
on t3.pkid = t4.fjid
left join zhxg_gy_ssfp_cwfp t5
on t4.pkid = t5.cwid
where 1 = 1
and t5.bjid in
#{item}
and t5.zyid in
#{item}
and t5.bmid in
#{item}
and t5.nj in
#{item}
and t1.ldid = #{value}
group by t1.pkid, t1.lcmc, t1.pxh,t6.XQMC,t2.ldmc
order by t1.pxh
【c】分析
如上,外层查询并没有使用到ldids 这个过滤条件,ldids 是在ResultMap中collection中子查询的过滤条件,我们这里构造一个假的结果列,
case
when '${ldids}' IS NULL then
NULL
else
'${ldids}'
end as ldids,
然后传递ldids 参数给子查询getLdByXqid :
这样在这个方法中就可以使用到ldids 这个过滤条件了:
and t1.pkid in
#{ldid}
以此类推,getldByXqid还能将参数继续传递下去,直到最下面一层查询。
注意:这里返回的假结果列不能是List类型的值,我们可以先将他们转换为String再进行传递,千万别踩坑,否则会报错(因为在数据库中,没有和List想对应的数据类型),笔者已经踩过了,切记切记。好了,就总结到这里,方便后面忘记了回来查看。