Mybatis plus 一对多关联查询分页不准确的问题

场景说明

比如有个服务器管理页面。要显示服务器信息,并且包含其拥有的账号信息。展示示例如下:
在这里插入图片描述
表结构信息如下:

t_server

在这里插入图片描述

t_server_user

在这里插入图片描述

查询sql

select
	ts.id,
	ts.host,
	tsu.id as user_id,
	tsu.user_name ,
	tsu.server_id ,
	tsu.port
from
	t_server ts
left join t_server_user tsu on
	ts.id = tsu.server_id

查询结果

在这里插入图片描述

问题点

我们在代码中定义的ResultMap

<resultMap id="QueryServerResultMap" type="com.yyoo.deployer.beans.ServerBean" extends="com.yyoo.deployer.mapper.ServerMapper.BaseResultMap">
        <collection property="userList"  ofType="com.yyoo.deployer.entity.ServerUserBean">
            <id column="user_id" property="id"/>
            <result column="user_name" property="userName" />
            <result column="pass" property="pass" />
            <result column="port" property="port" />
            <result column="server_id" property="serverId"/>
        </collection>
    </resultMap>

此处我们使用了collection标签。Mybatis会自动把上面的查询结果进行归类,形成一个server对象对应多个serverUser对象的形式。
这样做,不分页的时候是没有问题的。关键是分页的时候。

Mybatis在分页的时候生成的sql如下(下面均为查询第一页每页10条数据)

select
	ts.id,
	ts.host,
	tsu.id as user_id,
	tsu.user_name ,
	tsu.server_id ,
	tsu.port
from
	t_server ts
left join t_server_user tsu on
	ts.id = tsu.server_id
	limit 10 offset 0

此语句的查询结果为:(为了方便区分,结果为红框部分)
在这里插入图片描述

按照我们的规则,最终形成的ServerBean其实只有6条。

解决办法

1. 在 collection 标签上使用子查询

该办法会有n+1查询的问题,此处我们就不做详细讲解了。

2. 重新计算分页的limit参数

该办法计算起来有点难度,我们也不做讲解

3. 自定义分页查询sql

其实造成这个问题的关键在于,sql查询返回的条数,和Mybatis最终组装后的结果bean的条数不一致。要一致的关键在于,我们的查询主体是Server,我们将sql改造为如下方式

select
	ts.id,
	ts.host,
	tsu.id as user_id,
	tsu.user_name ,
	tsu.server_id ,
	tsu.port
from
	(select * from t_server limit 10 offset 0 ) ts
left join t_server_user tsu on
	ts.id = tsu.server_id

直接将分页参数编写好,查询第一页的10条server信息。

注:采用此方式,我们就不能使用Mybatis的分页机制了,参数不能使用Mybatis-plus的Page对象,需要自定义分页信息,采用list返回,而且还得自定义 count 的查询语句。配套的 count查询语句如下

select count(id)
        from t_server ts

我们的分页和前端显示都是针对server,所以此处的count查询也只针对server。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值