您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

分页插件PageHelper的使用及优化

时间:2020-02-28 09:57:18  来源:  作者:

介绍

PageHelper是mybatis框架上的一款分页插件。通过它友好的api设计,可省去写count,分页sql嵌套的繁琐工作。同时插件内部兼容不同数据库间(MySQL、Oracle等)的分页实现。开发者只需关注具体业务sql,其他的统计封装交给PageHelper插件动态处理。

作为JAVA后端开发者,这是一款必不可少的基础组件,大大减少了手动写分页列表查询的工作量。

官方开源地址:

GitHub - pagehelper/Mybatis-PageHelper: Mybatis通用分页插件

插件集成

添加maven依赖

<dependency>
  <groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>

添加mybatis配置插件

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

代码使用

表模型-用户表

CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) NOT NULL COMMENT '登录用户名',
  `password` varchar(255) NOT NULL COMMENT '登录密码',
  `telephone` varchar(255) DEFAULT NULL COMMENT '手机号',
  `idno` varchar(255) DEFAULT NULL COMMENT '身份证号',
  `name` varchar(255) DEFAULT NULL COMMENT '真实姓名',
  `sex` tinyint(1) DEFAULT NULL COMMENT '性别:  0:女, 1:男',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `update_by` varchar(255) DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_usr` (`user_name`) USING BTREE,
  KEY `idx_crt_time` (`create_time`) USING BTREE,
  KEY `idx_phone` (`telephone`) USING BTREE,
  KEY `idx_idno` (`idno`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

表模型-订单表

CREATE TABLE `order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '订单id',
  `user_id` bigint(20) unsigned NOT NULL COMMENT '用户id',
  `product_id` bigint(20) unsigned NOT NULL COMMENT '产品id',
  `price` decimal(8,2) DEFAULT '0.00' COMMENT '商品价格',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `update_by` varchar(255) DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;

查订单信息order-mApper

<!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.***.user.model.Order">
        <id column="id" property="id" />
        <result column="user_id" property="userId" />
        <result column="product_id" property="productId" />
        <result column="price" property="price" />
        <result column="create_time" property="createTime" />
        <result column="create_by" property="createBy" />
        <result column="update_time" property="updateTime" />
        <result column="update_by" property="updateBy" />
    </resultMap>
    <resultMap id="UserOrderResultMap" type="com.***.user.model.UserOrder" extends="BaseResultMap">
        <result column="user_name" property="userName" />
        <result column="user_mobile" property="userMobile" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, user_id, product_id, price, create_time, create_by, update_time, update_by    </sql>
    <sql id="findOrderByUserId_from_where" >
        from `order` o left join sys_user u  on u.id=o.user_id    </sql>
        <!-- 分页查询对应订单和用户信息-->
    <select id="findOrderByUserId" resultMap="UserOrderResultMap">
        select u.user_name,u.telephone, o.id, o.user_id, o.product_id, o.price, o.create_time, o.create_by, o.update_time, o.update_by        <include refid="findOrderByUserId_from_where" />
        order by o.create_time desc    </select>

OrderMapper类

public interface OrderMapper extends BaseMapper<Order> {
    List<UserOrder> findOrderByUserId();
}

PageHelper测试类

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class OrderServiceImplTest {
    @Autowired
    private IOrderService orderService;    @Test
    public void testFindUserOrderService(){        //PageHelper分页静态类.第一个参数当前页码从1开始,第二个参数每页记录数.
        PageHelper.startPage(1,3);
        List<UserOrder> userOrders = this.orderService.findOrderByUserId();
        //2.PageInfo<T> 封装返回业务对象,构建分页列表对象
        PageInfo<UserOrder> pageInfo = new PageInfo(userOrders);
        log.info("---findOrderByUserId page, total count is {}, list is {}",pageInfo.getTotal(),JSON.toJSONString(pageInfo.getList()));
    }
}

说明:测试类仅2步就实现了订单列表的分页查询,使用方法请参见代码注释。

执行测试类,在log日志中将看到以下sql执行。

分页插件PageHelper的使用及优化

 

从日志中可知(注意红框截图内容):

PageHelper动态的对count方法做了2个处理。

1.findOrderByUserId方法添加_COUNT后缀。

2.用select count(0) 替换原有sql select 查询字段,并去掉了order by排序。这是PageHelper根据业务sql做了优化,精简了sql,提高count的执行效率。

PageHelper动态的对业务sql添加了分页子句处理

演示程序使用mysql,所以在原有sql后面添加了LIMIT的分页子句。

优化

从上面的日志分析,我们大致可猜到PageHelper的动态处理。在count方法部分,插件动态的生成了一个findOrderByUserId_COUNT sql。该sql的规则也可以从PageHelper插件源代码中得到确认。

分页插件PageHelper的使用及优化

 

如上截图,count方法中,countMsId通过业务sql id和countSuffix后缀拼接生成。而这个countSuffix就是_COUNT。

接着看代码我们就不难发现,PageHelper插件会优先取工程中存在_COUNT后缀的sql,取不到则动态生成。

通过以上逻辑,我们就可以在项目中按它的规则,预先编写{业务id}_COUNT的sql,实现count分页逻辑的替换。

再回过来看我们之前的订单分页sql,from语句中使用left join和用户表关联。由于左连接在count上对order订单主表数量不产生任何影响。所以我们可以通过重写count方法,实现分页sql的优化。

原有left join sql

分页插件PageHelper的使用及优化

 

重写count后的优化sql

分页插件PageHelper的使用及优化

 

从优化后的sql可知,count从原有两张表变成了一张表。如果业务sql中相关表数量量比较大,或者其他join表比较多时,count优化将有比较好的效果。

最后再通过test类比较下两者的处理结果。

mapper文件新增findOrderByUserIdOpt和findOrderByUserIdOpt_COUNT sql

分页插件PageHelper的使用及优化

 

Test类

@Testpublic void testFindUserOrderService(){
    //PageHelper分页静态类.第一个参数当前页码从1开始,第二个参数每页记录数.    PageHelper.startPage(1,3);
    List<UserOrder> userOrders = this.orderService.findOrderByUserId();
    //PageInfo<T> 封装返回业务对象,构建分页列表对象    PageInfo<UserOrder> pageInfo = new PageInfo(userOrders);
    log.info("---findOrderByUserId page, total count is {}, list is {}",pageInfo.getTotal(),JSON.toJSONString(pageInfo.getList()));
    PageHelper.startPage(1,3);
    userOrders = this.orderService.findOrderByUserIdOpt();
    pageInfo = new PageInfo<>(userOrders);
    log.info("---findOrderByUserIdOpt page, total count is {}, list is {}",pageInfo.getTotal(),JSON.toJSONString(pageInfo.getList()));
}

执行结果:

分页插件PageHelper的使用及优化

 

从以上日志截图中可以看到,findOrderByUserIdOpt_COUNT已经按照单表方式来统计了。

总结

本文介绍了PageHelper分页插件的基本使用方法。并通过日志和代码分析,找到PageHelper count方法可以扩展优化的点。本文中的sql优化只是一个示例展示,提供一个思考的思路和方法,不做必要性讨论。项目中是否需做count优化,取决于业务场景和数据复杂性等综合因素。最后多谢能看到这里的同学,希望本文对你有所帮助。若有问题和建议,请多指正。



Tags:PageHelper   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前言提到插件,相信大家都知道,插件的存在主要是用来改变或者增强原有的功能,MyBatis中也一样。然而如果我们对MyBatis的工作原理不是很清楚的话,最好不要轻易使用插件,否则的话如...【详细内容】
2020-10-14  Tags: PageHelper  点击:(189)  评论:(0)  加入收藏
介绍PageHelper是mybatis框架上的一款分页插件。通过它友好的api设计,可省去写count,分页sql嵌套的繁琐工作。同时插件内部兼容不同数据库间(mysql、Oracle等)的分页实现。开...【详细内容】
2020-02-28  Tags: PageHelper  点击:(69)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条