前言:
当前朋友们对“pagehelperajax”大体比较讲究,兄弟们都想要知道一些“pagehelperajax”的相关知识。那么小编同时在网络上搜集了一些对于“pagehelperajax””的相关资讯,希望兄弟们能喜欢,咱们一起来学习一下吧!原创不易,请多多支持!对软件技术感兴趣的童鞋请关注我,后续技术分享更精彩。介绍
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)@Slf4jpublic 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动态的对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插件源代码中得到确认。
如上截图,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
重写count后的优化sql
从优化后的sql可知,count从原有两张表变成了一张表。如果业务sql中相关表数量量比较大,或者其他join表比较多时,count优化将有比较好的效果。
最后再通过test类比较下两者的处理结果。
mapper文件新增findOrderByUserIdOpt和findOrderByUserIdOpt_COUNT sql
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()));}
执行结果:
从以上日志截图中可以看到,findOrderByUserIdOpt_COUNT已经按照单表方式来统计了。
总结
本文介绍了PageHelper分页插件的基本使用方法。并通过日志和代码分析,找到PageHelper count方法可以扩展优化的点。本文中的sql优化只是一个示例展示,提供一个思考的思路和方法,不做必要性讨论。项目中是否需做count优化,取决于业务场景和数据复杂性等综合因素。最后多谢能看到这里的同学,希望本文对你有所帮助。若有问题和建议,请多指正。
标签: #pagehelperajax