气死了
气得我直接刚刚解决这个问题,就马上来写这篇文章了
这样也好,我能把整个过程完整记录下来
那开始吧
过程
最近在做毕设嘛,用的是RuoYi-Vue,用起来真的非常方便,极大的提高了开发效率。做起毕设或其他小项目真的非常容易,尤其加上它的代码生成工具,非常方便。而且我不光是在用,同时其实也是在学习,从中还是能学到很多东西的。
还有一个感触就是对于长期被业务折腾到半死,对代码失去信心的程序员,他们看到这样的开源项目,我相信他们肯定是开心,因为这种开源项目代码风格上很统一、规范标准执行的很到位,看起来真的赏心悦目。
问题简述
好了,回到正题!
今天做毕设,造数据测试的时候,发现分页功能失效了,前端调用后端分页接口返回的total
有问题
1 2 3 4 5
| {total: 10,…} code: 200 msg: "查询成功" rows: [{searchValue: null, createBy: null, createTime: "2022-03-18 20:36:55", updateBy: null,…},…] total: 10
|
total
总是返回当前数据的size
我很是不解,自认为对于ruoyi
分页流程很是熟悉,对照官网找问题,愣是找了半天没发现问题
官网:后台手册
| RuoYi
检查了半天没发现什么问题,只好先去找找有没有遇到同样问题的,果然,有不少
- https://cloud.tencent.com/developer/article/1786290
- https://zhuanlan.zhihu.com/p/159199627
- https://blog.csdn.net/qq_40942359/article/details/121429234
- https://www.cnblogs.com/mantishell/p/13674818.html
- https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108017635
看完后,大致明白是怎么回事,这其实是PageHelper
的问题
梳理流程
按照ruoyi
的流程理一遍
1、后端分页接口SysUserController extends BaseController
1 2 3 4 5 6 7 8 9 10 11
|
@PreAuthorize("@ss.hasPermi('system:user:list')") @GetMapping("/list") public TableDataInfo list(SysUser user) { startPage(); List<SysUser> list = userService.selectUserList(user); return getDataTable(list); }
|
点开startPage();
,这是父类BaseController
的方法
1 2 3 4 5 6 7 8 9 10 11 12
| protected void startPage() { PageDomain pageDomain = TableSupport.buildPageRequest(); Integer pageNum = pageDomain.getPageNum(); Integer pageSize = pageDomain.getPageSize(); if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) { String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); Boolean reasonable = pageDomain.getReasonable(); PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); } }
|
2、来到SysUserServiceImpl
1 2 3 4 5 6 7 8 9 10 11
|
@Override @DataScope(deptAlias = "d", userAlias = "u") public List<SysUser> selectUserList(SysUser user) { return userMapper.selectUserList(user); }
|
发现这里的service
就一行?
PageHelper
就是在这发挥了作用,进行了分页
其实我的问题就在这里,不过我要先把后面的流程走完
3、查到数据我们回到SysUserController
,这次关注他的return getDataTable(list);
1 2 3 4 5 6 7 8 9 10 11 12
|
@SuppressWarnings({"rawtypes", "unchecked"}) protected TableDataInfo getDataTable(List<?> list) { TableDataInfo rspData = new TableDataInfo(); rspData.setCode(HttpStatus.SUCCESS); rspData.setMsg("查询成功"); rspData.setRows(list); rspData.setTotal(new PageInfo(list).getTotal()); return rspData; }
|
这就是最终的相应结果,既然是total
出问题,那就重点关注setTotal
方法,直接点进new PageInfo(list).getTotal()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public PageInfo(List<T> list) { this(list, 8); }
public PageInfo(List<T> list, int navigatePages) { super(list); this.isFirstPage = false; this.isLastPage = false; this.hasPreviousPage = false; this.hasNextPage = false; if (list instanceof Page) { Page page = (Page)list; this.pageNum = page.getPageNum(); this.pageSize = page.getPageSize(); this.pages = page.getPages(); this.size = page.size(); if (this.size == 0) { this.startRow = 0L; this.endRow = 0L; } else { this.startRow = page.getStartRow() + 1L; this.endRow = this.startRow - 1L + (long)this.size; } } else if (list instanceof Collection) { this.pageNum = 1; this.pageSize = list.size(); this.pages = this.pageSize > 0 ? 1 : 0; this.size = list.size(); this.startRow = 0L; this.endRow = list.size() > 0 ? (long)(list.size() - 1) : 0L; }
if (list instanceof Collection) { this.calcByNavigatePages(navigatePages); }
}
|
最终调用的是下面的构造方法,那么就进到super(list);
1 2 3 4 5 6 7 8 9 10
| public PageSerializable(List<T> list) { this.list = list; if (list instanceof Page) { this.total = ((Page)list).getTotal(); } else { this.total = (long)list.size(); }
}
|
这是com.github.pagehelper
包下的,就是在这里为PageInfo
设置了total
,当然也是为我们最终相应设置了
???
Page哪里来的
4、Page
1 2 3 4 5
| package com.github.pagehelper;
public class Page<E> extends ArrayList<E> implements Closeable { ... }
|
从这里可以看出Page
继承了ArrayList
也是就实现了List
debug
结果如下,发现在执行完service
代码后,PageHelper
就已经完成这一步,那么自然就设置好了total
上面是正常流程梳理,接下看我的代码,哪里出了问题,导致total
总是错的
问题与解决
上面是举得ruoyi
原本的例子,因为我没有改动,所以也就没有问题
在我的模块上,我其他的代码实现也相同,就是在service
上又处理了一次
1 2 3 4 5 6 7 8 9 10
|
@Override public List<Task> selectTaskList(Task task) { return taskMapper.selectTaskList(task).stream().map(this::fill).collect(Collectors.toList()); }
|
这里的fill
就是又一个填充数据的流程
打印sql日志没有问题,是有分页流程的(查总数,然后limit
)
debug
发现这里list
变成了ArrayList,并非Page
,也就把total
设置为list.size()
其实问题早就在查到资料后发现了,但是大多数处理方法我都看不上,什么再调用PageHelper.startPage
,转换成PageInfo
之类的,都会让我怀疑我是否有必要用了
尤其是在已经使用了ruoyi
之后,重新在service做那简直太麻烦了,因为那样我还需要把ruoyi
封装在Controller
上的一些东西拿过去,折腾不了
最后,找到一种非常简单的方法解决了
就是,看上面的代码其是又调用了stream
的转换流程的,可能就是在这里PageHelper
出现了问题
那么试着将fill
方法变成void
,反正也是填充数据,没有影响的,改动后如下
1 2 3 4 5 6
| @Override public List<Task> selectTaskList(Task task) { List<Task> taskList = taskMapper.selectTaskList(task); taskList.forEach(this::fill); return taskList; }
|
这次debug
就是Page
对象了,一切都正常了
总结
如果你成功带入我的节奏,那很好,你认真看了;如果你发现其中问题了,那更好了,欢迎指正;如果你还能发现我另一个想讨论的问题,那我更开心了
我想讨论的就藏在
发现这里的service
就一行?
这句话里了
很奇怪我们的业务逻辑代码不都是几十行,上百行的吗?🤔
为什么service
就一行mapper
?
篇幅问题,一下在讨论吧!!!😁