请选择 进入手机版 | 继续访问电脑版

pageHelper分页失效解决方案

[复制链接]
菜鸡 发表于 2021-1-2 12:13:05 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
前言

      pageHelper是一款优秀的Mybatis分页插件,在项目中可以非常便利的使用,使开辟效率得到很大的提升,但不支持一对多效果映射的分页查询,所以在平常的使用时,对于一对多分页会出现分页错误,这篇文章主要对pageHelper分页错误举行重现以及提出管理方案。
分析

       mybatis举行一对多查询时,映射文件(mapper.xml)中的sql语句中使用的左毗连,pageHelper会自动对这条左毗连sql语句举行select count(0)的处置惩罚,并把效果作为分页布局的记载总数,然后自动将limit拼接到sql语句末了举行分页,由于左毗连查询时,毗连条件on条件不唯一(即一对多)时,效果会产生笛卡尔积,所以颠末pagehelper插件分页得到的记载总数和分页效果并不是预期的效果。
数据准备

共两个表:user、address,用户id与收货所在表中userId对应。
用户表【user】:11条数据

收货所在信息表【address】:4条数据

数据布局

  1. public class UserDto {    public int id;    public String name;    List addressList;}
复制代码
预期效果

要求对数据举行分页(每页5条),得到用户信息,每个用户信息带出对应收货信息, 用户id为2和3的用户各有两条收货所在信息,别的没有。渴望效果如下
  1. {  "code": 200,  "message": "success",  "data": {    "pageNum": 1,    "pageSize": 5,    "pages": 3,    "size": 5,    "total": 11,    "data": [      {        "id": 1,        "name": "张三",        "addressList": []      },      {        "id": 2,        "name": "李四",        "addressList": [          {            "id": 1,            "address": "陕西省宝鸡市",            "userId": 2          },          {            "id": 2,            "address": "陕西省延安市",            "userId": 2          }        ]      },      {        "id": 3,        "name": "王五",        "addressList": [          {            "id": 3,            "address": "陕西省西安市",            "userId": 3          },          {            "id": 4,            "address": "陕西省汉中市",            "userId": 3          }        ]      },      {        "id": 4,        "name": "钱六",        "addressList": []      },      {        "id": 5,        "name": "刘七",        "addressList": []      }    ]  }}
复制代码
问题重现

mybatis映射文件
  1.                                     SELECT    a.*,b.address,b.userId    FROM user a    LEFT JOIN address b on a.id=b.userId
复制代码
然后我们使用pageHelper举行分页,并输出日志
  1. SELECT count(0) FROM user a LEFT JOIN address b ON a.id = b.userIdPreparing: SELECT a.*,b.address,b.userId FROM user a LEFT JOIN address b on a.id=b.userId LIMIT ?Parameters: 5(Integer)Total: 5
复制代码
日志分析
第1行:举行数据总数的查询,作为数据的总条数total
第2-4行:举行分页效果的查询,查询出5条数据
从日志中可以看出
1. pageHelper插件拼接后的sql语句就不会输出正确的效果,更不会输出符合渴望的效果
2. pageHelper插件分两步查询,第一步查询出记载总数,第二步查询出分页效果
管理方案

方案一

思路:先分页查询出user表数据,然后在serviec服务层根据用户id查询对应的收货所在信息,并关联用户信息与收货信息。
service文件
  1. public List findAll(){    List userList=userMapper.findUser();    userList.forEach((item)-> {    item.setAddressList(userMapper.findByUserId(item.id));    });    return userList;}
复制代码
mybatis映射文件
  1.     SELECT * FROM user    SELECT * FROM address where userId=#{userId}
复制代码
方案二

思路:使用mybatis的嵌套子查询
  1.                                             select * from user    select a.* from address a where a.userId=#{userId}
复制代码
与嵌套映射布局的resultMap格式根本一致,一对多查询接纳的依旧是collection,区别在于collection中多了select与column属性,select用于加载子查询映射语句的id,它会从column属性指定的列中检索数据,作为参数通报给目的select语句即子查询。
缺点:这种方式虽然可以管理pagehelper一对多分页的问题,但在大型数据表与数据集上性能体现不佳,即产生'1+N'问题。
输出以下sql日志:首先通过主查询语句得到主表的数据总量作为分页的total,第二步通过limit得到前5条分页数据(就是‘1’),第三步将第二步得到效果作为参数通过子查询得到所在表的信息(就是‘N’)
  1. Preparing: SELECT count(0) FROM userParameters: Total: 1Preparing: select * from user LIMIT ?Parameters: 5(Integer)Preparing: select a.* from address a where a.userId=?Parameters: 1(Integer)Total: 0Preparing: select a.* from address a where a.userId=?Parameters: 2(Integer)Total: 2Preparing: select a.* from address a where a.userId=?Parameters: 3(Integer)Total: 2Preparing: select a.* from address a where a.userId=?Parameters: 4(Integer)Total: 0Preparing: select a.* from address a where a.userId=?Parameters: 5(Integer)Total: 0
复制代码
方案三

思路:弃用pageHelper插件,自界说分页查询,先对主表(user)举行分页,并把分页效果作为虚拟表与副表(address)举行左毗连查询
  1.                                                              SELECT        a.*,        b.address,        b.userId    FROM            ( SELECT * FROM user LIMIT #{size} ) a                LEFT JOIN address b ON a.id = b.userid
复制代码
 

来源:https://blog.csdn.net/douzhenwen/article/details/112025079
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )