背景

mybatis-plus自带一个分页插件,能够帮助我们快速的完成分页,详细用法可以看官网。但是分页插件只适用于基础的单表,对于需要聚合查询的一对多情况,有个很深的坑。

正确示例

示例1

使用子查询的方式,查询子实体,再collection标签里指定子查询语句select和关联的字段column

这个column也可以理解为子查询语句所需的参数,需要把主查询的哪个字段作为参数传入到子查询的查询方法里

// 实体类
@Data
public class NcsErBxzbDTO {
// 主键
private String pkJkbx;
// 单据编号
private String djbh;
// 单据日期
private String djrq;
// 单据总金额
private BigDecimal total;
// 事由
private String zy;
// 借款保险部门主键
private String deptId;
// 借款报销部门名称
private String deptName;
// 财务组织
private String pkFiorg;
// 明细
private List<ErBusitem> erBusitemList;

@Data
public static class ErBusitem {
private String pkBusitem;
// 不含税金额
private String amountExcludingTax;
// 税额
private String tax;
}
}

// mapper接口
List<NcsErBxzbDTO> getList(@Param("query") ErBxzbQO qo, @Param("page") IPage<NcsErBxzbDTO> page);
<!-- sql语句 -->
<resultMap id="NcsErBxzbDTOMap" type="org.jeecg.modules.ncs.dto.NcsErBxzbDTO">
<id column="pk_jkbx" property="pkJkbx"/>
<result column="PK_FIORG" property="pkFiorg"/>
<result column="TOTAL" property="total"/>
<result column="DJBH" property="djbh"/>
<result column="DJRQ" property="djrq"/>
<result column="ZY" property="zy"/>
<result column="DEPTID" property="deptId"/>

<collection property="erBusitemList"
ofType="org.jeecg.modules.ncs.dto.NcsErBxzbDTO$ErBusitem"
select="getErBusitemListByPkJkbx"
column="pk_jkbx"
>
</collection>
</resultMap>


<select id="getList" resultMap="NcsErBxzbDTOMap">
SELECT
er_bxzb.pk_jkbx,
er_bxzb.PK_FIORG,
er_bxzb.TOTAL,
er_bxzb.DJBH,
er_bxzb.DJRQ,
er_bxzb.ZY,
er_bxzb.DEPTID
FROM
er_bxzb er_bxzb
<where>
<if test="query.pkFiorg != null and query.pkFiorg != ''">
and er_bxzb.PK_FIORG = #{query.pkFiorg}
</if>
<if test="query.deptId != null and query.deptId != ''">
and er_bxzb.DEPTID = #{query.deptId}
</if>
<if test="query.startDate != null and query.startDate != ''">
AND TO_DATE(er_bxzb.DJRQ, 'YYYY-MM-DD HH24:MI:SS') &gt;= TO_DATE(#{query.startDate}, 'YYYY-MM-DD')
</if>
<if test="query.endDate != null and query.endDate != ''">
AND TO_DATE(er_bxzb.DJRQ, 'YYYY-MM-DD HH24:MI:SS') &lt; TO_DATE(#{query.endDate}, 'YYYY-MM-DD') + 1
</if>
<if test="query.djbh != null and query.djbh != ''">
<bind name="djbhBind" value="'%'+query.djbh+'%'"/>
AND er_bxzb.DJBH like #{djbhBind}
</if>
AND er_bxzb.dr = 0
</where>
ORDER BY
djrq DESC,
djbh DESC
</select>

<select id="getErBusitemListByPkJkbx" resultType="org.jeecg.modules.ncs.dto.NcsErBxzbDTO$ErBusitem">
SELECT
er_busitem.pk_busitem pkBusitem,
er_busitem.defitem25 amountExcludingTax,
er_busitem.defitem26 tax
FROM
er_busitem
<where>
er_busitem.pk_jkbx = #{pkJkbx}
</where>
</select>

示例2

这里不写具体的代码,就稍微描述一下

不再依赖mybatis完成子查询,而是自己通过编码的方式完成子查询
如示例1所示,不需要再resultMap里写collection,而是直接执行主表的单表查询
当主表的数据查询出来后,在代码里循环集合或数组,对每个对象执行子查询,然后将查询出的结果手动set到实体的属性中

错误示例

在示例1的基础上,在collection里写id,result等标签,不写sql,column标签
在主表的查询语句的基础上直接left join子表
不写子表的单独查询的语句,而是只有一个关联查询
这样查出来的结果分页就会不正确。
比如,主表1条,子表3条,他们是关联的,此时如果前端传过来的pageSize是5,那么这一个主表对象就占了3个位置,而不是原本的占一个位置