创作来源:本来项目是用mybatis的mybatisX里面默认添加的分页插件来实现项目分页查询功能,其实也挺简便的,但是希望mybatis全部升级为plus,也就把这个也改了,其实个人感觉mybatis本身的一些mapper方法也挺好用的,有一些也很方便,但是大体上还是plus优先。
注意:在未引入分页插件的情况下,
MybatisPlus
是不支持分页功能的,IService
和BaseMapper
中的分页方法都无法正常起效。 所以,我们必须配置分页插件。
在项目中新建一个配置类MyBatisConfiguration,放在项目的config包下面,当然根据个人喜好。如下图所示:
在配置类添加MyBatisConfiguration配置信息,代码如下:
参考官方文档:分页插件 | MyBatis-Plus
@Configuration
public class MyBatisConfiguration {
//mybatis-plus分页插件
//详细文档:https://baomidou.com/guide/page.html#使用-starter
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 1.创建分页插件
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(1000L);
// 2.添加分页插件
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
在配置好后接下来就是通用分页实体等等的编写及接口的开发。
给PageQuery类定义一些通用属性并且提供一些反复用得到的方法
默认通过create_time,update_time来排序,当然这些要和数据库字段统一
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "分页查询实体")
public class PageQuery {
@ApiModelProperty("页码")
private Long pageNo;
@ApiModelProperty("每页显示记录数")
private Long pageSize;
@ApiModelProperty("排序字段")
private String sortBy;
@ApiModelProperty("是否升序")
private Boolean isAsc;
public Page toMpPage(OrderItem ... items){
// 1.分页条件
Page page = Page.of(pageNo, pageSize);
// 2.排序条件
if(StrUtil.isNotBlank(sortBy)){
// 不为空
OrderItem orderItem=new OrderItem();
//排序方式
orderItem.setAsc(isAsc);
//排序字段
orderItem.setColumn(sortBy);
page.addOrder(orderItem);
}else if(items != null){
// 为空,默认排序
page.addOrder(items);
}
return page;
}
public Page toMpPage(String defaultSortBy, boolean isAsc){
OrderItem orderItem=new OrderItem();
//排序方式
orderItem.setAsc(isAsc);
//排序字段
orderItem.setColumn(defaultSortBy);
return this.toMpPage(orderItem);
}
public Page toMpPageDefaultSortByCreateTimeDesc() {
return toMpPage("create_time", false);
}
public Page toMpPageDefaultSortByUpdateTimeDesc() {
return toMpPage("update_time", false);
}
}
@Data
public class EmployeePageQueryDTO extends PageQuery implements Serializable {
// //页码
// private Long pageNo;
// //每页显示记录数
// private Long pageSize;
//员工姓名
private String name;
}
因为分页查询所需的就3个属性,总记录数,总页数,分页查询得到的数据,所以这个是统一的VO类
/**
* 封装分页查询结果
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
private Long total; //总记录数
private Long pages; //总页数
private List records; //当前页数据集合
}
controller中的方法基本没有什么影响,该怎么写就怎么写,这里提供两种通过接口传参数的案例
/**
* 员工分页查询
* @param employeePageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("员工分页查询")
public Resultpage(EmployeePageQueryDTO employeePageQueryDTO){
log.info("员工分页查询,参数为:{}",employeePageQueryDTO);
PageResult pageResult= employeeService.pageQuery(employeePageQueryDTO);
return Result.success(pageResult);
}
/**
* 历史订单查询
*
* @param page
* @param pageSize
* @param status 订单状态 1待付款 2待接单 3已接单 4已完成 5已取消
* @return
*/
@GetMapping("/historyOrders")
@ApiOperation("历史订单查询")
public Result page(Long page, Long pageSize, Integer status) {
PageResult pageResult = orderService.pageQueryUser(page, pageSize, status);
return Result.success(pageResult);
}
public interface EmployeeService extends IService {
/**
* 分页查询
* @param employeePageQueryDTO
* @return
*/
PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);
}
public interface OrderService extends IService {
/**
* 历史订单分页查询
* @param pageNum
* @param pageSize
* @param status 订单状态 1待付款 2待接单 3已接单 4已完成 5已取消
* @return
*/
PageResult pageQueryUser(Long pageNum, Long pageSize, Integer status);
}
两种不同的接口传到service参数在Impl有两种不同写法,实际上就是一种基本的,但是我之前在PageQuery分页实体类里面写了对应的便捷方法
@Service
public class EmployeeServiceImpl extends ServiceImpl implements EmployeeService {
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
//使用mybatisPlus自带的分页插件
//mybatisX里面默认添加的分页插件和该插件只能存在一个,如果想转换必须导包
//mybatisX里面的属性为int
//mybatisPlus里面的属性为long
// 1.构建分页条件
Page page = employeePageQueryDTO.toMpPageDefaultSortByCreateTimeDesc();
// 2.分页查询
Page p=lambdaQuery()
.like(employeePageQueryDTO.getName() != null,Employee::getName, employeePageQueryDTO.getName())
.page(page);
// 3.调用插件获得数据
//获得总的记录数
long total = p.getTotal();
//获得总的页数
long pages = p.getPages();
//获得当前页数据集合
List records = p.getRecords();
// 4.返回封装好的分页结果
return new PageResult(total,pages,records);
}
}
在上面这个Impl里面我使用了之前已经PageQuery分页实体类封装的方法来创建分页条件
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl implements OrderService {
/**
* 历史订单查询
*
* @param pageNum
* @param pageSize
* @param status 订单状态 1待付款 2待接单 3已接单 4已完成 5已取消
* @return
*/
@Override
public PageResult pageQueryUser(Long pageNum, Long pageSize, Integer status) {
// 1.构建条件
// 1.1.分页条件
Page page = Page.of(pageNum, pageSize);
OrdersPageQueryDTO ordersPageQueryDTO=new OrdersPageQueryDTO();
ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
ordersPageQueryDTO.setStatus(status);
// 分页条件查询
Pagep=lambdaQuery()
.like(ordersPageQueryDTO.getNumber()!=null,Orders::getNumber,ordersPageQueryDTO.getNumber())
.like(ordersPageQueryDTO.getPhone()!=null,Orders::getPhone,ordersPageQueryDTO.getPhone())
.eq(ordersPageQueryDTO.getUserId()!=null,Orders::getUserId,ordersPageQueryDTO.getUserId())
.eq(ordersPageQueryDTO.getStatus()!=null,Orders::getStatus,ordersPageQueryDTO.getStatus())
.ge(ordersPageQueryDTO.getBeginTime()!=null,Orders::getOrderTime,ordersPageQueryDTO.getBeginTime())
.le(ordersPageQueryDTO.getEndTime()!=null,Orders::getOrderTime,ordersPageQueryDTO.getEndTime())
//按订单时间排序
.orderByDesc(Orders::getOrderTime)
.page(page);
List ordersList = p.getRecords();
List list = new ArrayList();
// 查询出订单明细,并封装入OrderVO进行响应
if (ordersList!=null&& ordersList.size()>0){
for (Orders orders : ordersList) {
Long orderId = orders.getId();//订单id
// 查询订单明细
// List orderDetails = orderDetailMapper.getByOrderId(orderId);
QueryWrapper OrderDetailWrapper = new QueryWrapper<>();
OrderDetailWrapper.lambda().eq(OrderDetail::getOrderId, orderId);
List orderDetails =orderDetailMapper.selectList(OrderDetailWrapper);
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(orders, orderVO);
orderVO.setOrderDetailList(orderDetails);
list.add(orderVO);
}
}
return new PageResult(p.getTotal(),p.getPages(),list);
}
}
这个Impl就是按照普通的构建分页条件,传入所需要的参数,在设置排序方式在分页条件查询里面orderByDesc(Orders::getOrderTime),但是两种Impl的对分页查询的操作实际原理是一样的。都是经过类似下面的操作:
// 1.1.分页条件
Page page = Page.of(pageNum, pageSize);
// 分页条件查询
Pagep=lambdaQuery()
.like(ordersPageQueryDTO.getNumber()!=null,Orders::getNumber,ordersPageQueryDTO.getNumber())
.like(ordersPageQueryDTO.getPhone()!=null,Orders::getPhone,ordersPageQueryDTO.getPhone())
.eq(ordersPageQueryDTO.getUserId()!=null,Orders::getUserId,ordersPageQueryDTO.getUserId())
.eq(ordersPageQueryDTO.getStatus()!=null,Orders::getStatus,ordersPageQueryDTO.getStatus())
.ge(ordersPageQueryDTO.getBeginTime()!=null,Orders::getOrderTime,ordersPageQueryDTO.getBeginTime())
.le(ordersPageQueryDTO.getEndTime()!=null,Orders::getOrderTime,ordersPageQueryDTO.getEndTime())
//按订单时间排序
.orderByDesc(Orders::getOrderTime)
.page(page);
List ordersList = p.getRecords();
return new PageResult(p.getTotal(),p.getPages(),list);
// 1.构建分页条件
Page page = employeePageQueryDTO.toMpPageDefaultSortByCreateTimeDesc();
// 2.分页查询
Page p=lambdaQuery()
.like(employeePageQueryDTO.getName() != null,Employee::getName, employeePageQueryDTO.getName())
.page(page);
// 3.调用插件获得数据
//获得总的记录数
long total = p.getTotal();
//获得总的页数
long pages = p.getPages();
//获得当前页数据集合
List records = p.getRecords();
// 4.返回封装好的分页结果
return new PageResult(total,pages,records);
记得那个分页条件查询那边
.like(employeePageQueryDTO.getName() != null,Employee::getName, employeePageQueryDTO.getName())
记得在第一个参数加上
employeePageQueryDTO.getName() != null
不加的话如果你是字符串,到时候sql查询的时候拼接就会出现 %null% 的情况导致分页查询无结果
注意 : 在写serviceImpl的时候,我本来想留着一部分的分页查询,但是同一个impl里面似乎不允许导入两种分页查询插件,导入一个另外一个就报错,只能使用一种,而且mybatisX的分页插件里面有属性是Integer,而mybatisplus里面的分页插件是Long ,如果你这个项目想两个都用,在封装分页实体类就特别麻烦,要弄两种。不建议。
上面的serviceImpl还省略了mapper的注入,实际操作 还是要注入的
mapper里面之前mybatis写的分页查询功能,当然是删掉了或注释掉了
@Mapper
public interface EmployeeMapper extends BaseMapper {
// Page pageQueuery(EmployeePageQueryDTO employeePageQueryDTO);
}
该类继承了
IPage
类,实现了简单分页模型
如果你要实现自己的分页模型可以继承Page
类或者实现IPage
类,可参考官方文档:分页插件 | MyBatis-Plus下面给出这个的一些属性,方便使用方法的时候调用对应需要的方法:
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
records | List | emptyList | 查询数据列表 |
total | Long | 0 | 查询列表总记录数 |
size | Long | 10 | 每页显示条数,默认 10 |
current | Long | 1 | 当前页 |
orders | List | emptyList | 排序字段信息,允许前端传入的时候,注意 SQL 注入问题,可以使用 SqlInjectionUtils.check(...) 检查文本 |
optimizeCountSql | boolean | true | 自动优化 COUNT SQL 如果遇到 jSqlParser 无法解析情况,设置该参数为 false |
optimizeJoinOfCountSql | boolean | true | 自动优化 COUNT SQL 是否把 join 查询部分移除 |
searchCount | boolean | true | 是否进行 count 查询,如果只想查询到列表不要查询总记录数,设置该参数为 false |
maxLimit | Long | 单页分页条数限制 | |
countId | String | xml 自定义 count 查询的 statementId 也可以不用指定在分页 statementId 后面加上 _mpCount 例如分页 selectPageById 指定 count 的查询 statementId 设置为 selectPageById_mpCount 即可默认找到该 SQL 执行 |