分页查询的优点
所谓分页查询,就是查询结果数据较多时,采用按页显示的方法,而不是一次性全部显示
分页的优点:
1.服务器:一次性查询出所有的信息,服务器压力大,采用分页查询服务器压力小
2.客户端:一次性显示所有信息所需流量过大,加载时间也会加长,而分页显示不存在此问题
3.用户体验上: 一般最有价值的数据也会在前几页显示,方便用户记忆,多查询出来的数据使用几率较低
同样实现分页查询需要我们在开发时多几个步骤:
PageHelper实现分页查询原理
可以通过在数据库中添加limit关键字的方法实现分页查询
但是在查询过程中,需要我们计算相关的分页信息和参数
limit 0,10 limit 10,10
所以我们采用框架来让我们更高效的完成分页功能
PageHelper框架的分页原理就是在程序运行时,在sql语句尾部添加limit关键字,并按照分页信息向limit后追加分页数据
首先:添加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
PageHelper的使用
编写持久层
// 分页查询所有订单的方法
// 使用PageHepler框架完成分页查询原理是在sql语句运行时,会在sql语句后添加limit关键字
// 所以方法在持久层中编写时,没有任何分页的特征,也无需关注分页业务(注解和xml都是一样的)
@Select("select id,user_id,commodity_code,count,money from order_tbl")
List<Order> findAllOrders();
这个方法并不需要任何分页的参数或返回值,sql也不需要编写limit
都是在业务逻辑层中由PageHelper框架处理的
编写业务逻辑层
先编写一个方法使用PageHelper的功能
先不用写接口,直接在业务逻辑层中写方法
// 分页查询所有订单信息的方法
// page是页码,pageSize是每页条数
public PageInfo<Order> getAllOrdersByPage(Integer page,Integer pageSize){
// PageHelper框架使用分页功能的核心代码,是要在执行查询数据库的代码运行之前
// 编写PageHelper.startPage(page,pageSize)方法,设置分页查询的条件
// 这里的page如果是1,就表示查询第1页
PageHelper.startPage(page,pageSize);
// 上面分页条件设置好之后,下面执行查询操作,这个操作的末尾就会被添加limit
List<Order> list= orderMapper.findAllOrders();
// 查询结果list只包含分页数据,并不能包含分页信息(总页数,总条数等)
// 所以要利用PageHelper框架提供的PageInfo类型来返回信息
// PageInfo和SpringData的Page接口是类似的,也是既能包含数据,又能包含分页信息
// 使用方式是直接实例化,它的构造方法中会自动按上面分页查询计算需要的分页信息
return new PageInfo<>(list);
}
编写控制层
@Autowired
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
private OrderServiceImpl orderService;
//...
@GetMapping("/page")
@ApiOperation("分页查询所有订单")
@ApiImplicitParams({
@ApiImplicitParam(value = "页码",name="page",example ="1" ),
@ApiImplicitParam(value = "每页条数",name="pageSize",example ="10" )
})
public JsonResult<PageInfo<Order>> pageOrder(Integer page,Integer pageSize){
PageInfo<Order> pageInfo=
orderService.getAllOrdersByPage(page,pageSize);
return JsonResult.ok("查询完成",pageInfo);
}
附:PageInfo全部分页信息属性
//当前页
private int pageNum;
//每页的数量
private int pageSize;
//当前页的行数量
private int size;
//当前页面第一个元素在数据库中的行号
private int startRow;
//当前页面最后一个元素在数据库中的行号
private int endRow;
//总页数
private int pages;
//前一页页号
private int prePage;
//下一页页号
private int nextPage;
//是否为第一页
private boolean isFirstPage;
//是否为最后一页
private boolean isLastPage;
//是否有前一页
private boolean hasPreviousPage;
//是否有下一页
private boolean hasNextPage;
//导航条中页码个数
private int navigatePages;
//所有导航条中显示的页号
private int[] navigatepageNums;
//导航条上的第一页页号
private int navigateFirstPage;
//导航条上的最后一页号
private int navigateLastPage;
使用JsonPage来返回结果
当前我们分页查询使用的类型是PageInfo
如果将此类型来做业务逻辑的返回值,当前方法作为dubbo生产者对外提供服务时
消费者调用该服务需要使用PageInfo类型对象来进行接收,这样消费者也需要加上PageHelper依赖,显然是不合理的
所以在设计通用模块时,可以添加一个专门用于返回分页结果的类,JsonPage,代替PageInfo
这样当我们在使用时,所有分页或类似的操作,就都可以使用此类
<!--
将PageHelper框架分页查询结果对象PageInfo转换为JsonPage类型
我们需要再commons模块中添加PageHelper的依赖
-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
在restful包中新建一个JsonPage类
@Data
public class JsonPage<T> implements Serializable {
// 当前类在实际开发中替代Page/PageInfo这样的由框架提供的分页信息类
// 这样当前微服务项目所有分页业务都可以使用这个类型,实现通用
// 属性的个数原则是满足前端需要即可,这里列出最基本的分页信息属性
@ApiModelProperty(value = "总页数",name = "totalPages")
private Integer totalPages;
@ApiModelProperty(value = "总条数",name = "totalCount")
private Long totalCount;
@ApiModelProperty(value = "页码",name = "page")
private Integer page;
@ApiModelProperty(value = "每页条数",name = "pageSize")
private Integer pageSize;
// JsonPage对象要能够报错分页数据
@ApiModelProperty(value = "分页数据",name = "list")
private List<T> list;
// 下面编写一个方法,能够实现将PageInfo类型对象转换为JsonPage对象返回
public static <T> JsonPage<T> restPage(PageInfo<T> pageInfo){
// 将参数pageInfo对象相同意义的属性赋值到JsonPage对象中,来完成转换
JsonPage<T> jsonPage=new JsonPage<>();
jsonPage.setTotalPages(pageInfo.getPages());
jsonPage.setTotalCount(pageInfo.getTotal());
jsonPage.setPage(pageInfo.getPageNum());
jsonPage.setPageSize(pageInfo.getPageSize());
// 分页数据也要赋值过来
jsonPage.setList(pageInfo.getList());
// 最后返回转换完成的对象
return jsonPage;
}
}
在service业务逻辑层接口添加此方法
// 返回JsonPage类型的分页查询订单的方法
JsonPage<Order> getAllOrdersByPage(Integer page,Integer pageSize);
剩下就是实现类和控制器类进行修改