当前位置: 首页 > news >正文

通用分页处理:从繁琐到简洁的转变

文章目录

  • 一、前言
  • 二、通用分页处理方法的实现
  • 三、使用案例
  • 四、总结

一、前言

在处理需要对整个表的数据进行处理或者数据同步的场景中,由于数据量通常较大,我们常常会采用不断地分页查询来进行操作。通常情况下,我们需要编写一个分页查询数据表的方法,例如下面的selectUserPageData方法,并且按照类似如下的逻辑来实现:

public void oldPageBatch() {int currentPage = 1;int pageCount = 1000;PageInfo<User> page = selectUserPageData(currentPage, pageCount);log.info("[PAGE-BATCH-USER]:pageNum: {},pageSize: {},totalData: {}", currentPage, pageCount, page.getTotal());doBatchHand(page.getList());// 处理后面数据boolean hasNextPage = page.isHasNextPage();for (int i = 2; i <= page.getPages(); i++) {PageInfo<User> tmpPage = selectUserPageData(i, pageCount);log.info("[PAGE-BATCH-USER]:pageNum:{}, pageSize:{}, totalData:{}", i, pageCount, tmpPage.getTotal());doBatchHand(tmpPage.getList());}
}

二、通用分页处理方法的实现

上面那样的实现方式虽然能够达成所需的功能,然而存在一定的繁琐性。而且,倘若后续遇到类似的场景,还需要重新编写一遍类似的代码。在多次遭遇此类场景之后,我开始思考如何构建一个通用的分页处理方法。那应该如何实现呢?

首先,在不同的业务中,上述代码的主体逻辑基本一致,唯有分页方法selectUserPageData和批量的逻辑处理方法doBatchHand在各个业务代码里有所不同。针对这种情况,我借助设计模式中的模板方法模式,提取出公共的逻辑,再由子类来实现各自特定的分页方法selectUserPageData和批量的逻辑处理方法doBatchHand

其次,对于分页操作,可以利用通用的PageHelper组件来进行简化。如此一来,子类无需再编写分页方法selectUserPageData,直接传入原有的非分页的查询方法即可。

实现的具体步骤如下:

一、引入依赖

<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.10</version>
</dependency>

二、创建AbstractPageBatchService

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import java.util.List;/*** @author fhey* @Date 2024/7/10 17:37* @Description 类注释*/
@Slf4j
public abstract class AbstractPageBatchService<T> {private PageInfo<T> selectPageData(int pageNum, int pageSize) {PageHelper.startPage(pageNum, pageSize, true, false, false);return PageInfo.of(selectAll());}public void batchHand(int pageCount) {String className = this.getClass().getSimpleName();int currentPage = 1;PageInfo page = selectPageData(currentPage, pageCount);log.info("[PAGE - BATCH - {}]:pageNum: {},pageSize: {},totalData: {}",className, currentPage, pageCount, page.getTotal());doBatchHand(page.getList());// 处理后面数据boolean hasNextPage = page.isHasNextPage();for (int i = 0; i < page.getPages(); i++) {PageInfo tmpPage = selectPageData(i + 1, pageCount);log.info("[PAGE-BATCH-{}]:pageNum:{}, pageSize:{}, totalData:{}", className, i + 1, pageCount, tmpPage.getTotal());doBatchHand(tmpPage.getList());}while (hasNextPage) {++currentPage;PageInfo tmpPage = selectPageData(currentPage, pageCount);hasNextPage = tmpPage.isHasNextPage();log.info("[PAGE-BATCH-{}]:pageNum:{}, pageSize:{}, totalData:{}", className, currentPage, pageCount, tmpPage.getTotal());doBatchHand(tmpPage.getList());}}abstract List<T> selectAll();abstract void doBatchHand(List<T> list);
}

如此一来,当需要进行分页处理时,只需继承AbstractPageBatchService,并实现全量查询方法selectAll和处理逻辑方法doBatchHand即可。

三、使用案例

下面以分页查询用户表,并批量输出用户id来展示使用的示例:

  1. UserPageBatchHand
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fhey.mapper.UserMapper;
import com.fhey.model.po.User;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;/*** @author fhey* @Date 2024/7/10 17:37* @Description 类注释*/
@Slf4j
@Component
public class UserPageBatchHand extends AbstractPageBatchService<User>{@AutowiredUserMapper userMapper;@OverrideList<User> selectAll() {LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.isNotNull(User::getId);List<User> userList = userMapper.selectList(wrapper);return userList;}//因为是测试,只把主键id打印出来@Overridevoid doBatchHand(List<User> list) {System.out.println("UserBatchHand start");list.forEach(a-> System.out.println(a.getId()));System.out.println("UserBatchHand end");}
}
  1. UserController
package com.fhey.controller;import com.fhey.model.po.User;
import com.fhey.service.pagebatch.UserPageBatchHand;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;/*** @author fhey* @date 2024/7/10 14:07* @details 详情*/
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {private final UserPageBatchHand userPageBatchHand;@GetMapping("/test/userPageBatchHand")public void searchStuById() {userPageBatchHand.batchHand(10);}
}

由于数据量较多,这里仅展示第一次处理的日志,测试结果如下:

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@46beaceb] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@73a332ec] will not be managed by Spring
==>  Preparing: SELECT count(0) FROM user WHERE deleted = 0 AND (id IS NOT NULL)
==> Parameters: 
<==    Columns: count(0)
<==        Row: 2003
<==      Total: 1
==>  Preparing: SELECT id,user_name,create_time,create_user,update_time,update_user,deleted FROM user WHERE deleted=0 AND (id IS NOT NULL) LIMIT ?
==> Parameters: 10(Integer)
<==    Columns: id, user_name, create_time, create_user, update_time, update_user, deleted
<==        Row: 1820471883522285569, 小明139, 2024-08-05 22:48:14.0, testUser, 2024-08-05 22:48:14.0, testUser, 0
<==        Row: 1820472953300492290, 小明509, 2024-08-05 22:52:29.0, testUser, 2024-08-05 22:52:29.0, testUser, 0
<==        Row: 1820493273394765825, 小明267, 2024-08-06 00:13:14.0, testUser, 2024-08-06 00:13:14.0, testUser, 0
<==        Row: 1820497296638267393, 小明7959, 2024-08-06 00:29:13.0, testUser, 2024-08-06 00:29:13.0, testUser, 0
<==        Row: 1820497296638267394, 小明7682, 2024-08-06 00:29:13.0, testUser, 2024-08-06 00:29:13.0, testUser, 0
<==        Row: 1820497296638267395, 小明2768, 2024-08-06 00:29:13.0, testUser, 2024-08-06 00:29:13.0, testUser, 0
<==        Row: 1820497296638267396, 小明4420, 2024-08-06 00:29:13.0, testUser, 2024-08-06 00:29:13.0, testUser, 0
<==        Row: 1820497296638267397, 小明4523, 2024-08-06 00:29:13.0, testUser, 2024-08-06 00:29:13.0, testUser, 0
<==        Row: 1820497296638267398, 小明1434, 2024-08-06 00:29:13.0, testUser, 2024-08-06 00:29:13.0, testUser, 0
<==        Row: 1820497296638267399, 小明6403, 2024-08-06 00:29:13.0, testUser, 2024-08-06 00:29:13.0, testUser, 0
<==      Total: 10
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@46beaceb]
2024-08-06 16:12:13.599  INFO 18396 --- [nio-9000-exec-3] c.f.s.p.AbstractPageBatchService         : [PAGE - BATCH - UserPageBatchHand]:pageNum: 1,pageSize: 10,totalData: 2003
UserBatchHand start
1820471883522285569
1820472953300492290
1820493273394765825
1820497296638267393
1820497296638267394
1820497296638267395
1820497296638267396
1820497296638267397
1820497296638267398
1820497296638267399
UserBatchHand end

测试结果表明,成功实现了分页,第一次仅查出 10 条数据,并按处理逻辑打印出数据的id

四、总结

在处理大量数据的表操作或数据同步时,为应对数据量过大的情况,通常采用分页查询。最初的实现方式存在繁琐和重复编写的问题。经过多次类似场景的经历,通过运用模板方法模式和通用的PageHelper组件,构建了更高效的通用分页处理方法此通用分页处理方法提高了代码的复用性和可维护性,减少了重复编写的工作量。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PYTHON专题-(7)python都有包了?
  • 【王道数据结构-第二章-线性表算法题】
  • 50etf期权行权采用什么交割方式 ?
  • Python爬虫与MySQL完美结合:从环境搭建到实战优化
  • Linux——文件(1)
  • SQL注入实例(sqli-labs/less-9)
  • Ubuntu22.04安装Docker教程
  • 微信开放平台更换服务器证书通知
  • Tomcat 漏洞
  • 基于飞腾E2000的科东软件Intewell工业实时操作系统方案
  • 音质提升秘籍:专业音频剪辑软件汇总
  • 【蘑菇书EasyRL】强化学习,笔记整理
  • 数据结构(5.5_1)——哈夫曼树
  • 深入解析 Vue.js 的 nextTick
  • 【从零开始一步步学习VSOA开发】创建VSOA的server端
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 【面试系列】之二:关于js原型
  • CSS 提示工具(Tooltip)
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • input实现文字超出省略号功能
  • Laravel 菜鸟晋级之路
  • Lsb图片隐写
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Spark学习笔记之相关记录
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Swift 中的尾递归和蹦床
  • 开源地图数据可视化库——mapnik
  • 深入浅出Node.js
  • 什么软件可以剪辑音乐?
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 湖北分布式智能数据采集方法有哪些?
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • #Linux(权限管理)
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (2)STM32单片机上位机
  • (rabbitmq的高级特性)消息可靠性
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (安卓)跳转应用市场APP详情页的方式
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (六)DockerCompose安装与配置
  • (论文阅读11/100)Fast R-CNN
  • (一)基于IDEA的JAVA基础12
  • (转)setTimeout 和 setInterval 的区别
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .mp4格式的视频为何不能通过video标签在chrome浏览器中播放?
  • .Net 基于.Net8开发的一个Asp.Net Core Webapi小型易用框架
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @RequestBody的使用
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略
  • [AHK] WinHttpRequest.5.1报错 0x80092004 找不到对象或属性
  • [BUG] Authentication Error