MyBatis-Plus使用分页插件实现分页查询功能

创作来源:本来项目是用mybatis的mybatisX里面默认添加的分页插件来实现项目分页查询功能,其实也挺简便的,但是希望mybatis全部升级为plus,也就把这个也改了,其实个人感觉mybatis本身的一些mapper方法也挺好用的,有一些也很方便,但是大体上还是plus优先。

一、配置分页插件

注意:在未引入分页插件的情况下,MybatisPlus是不支持分页功能的,IServiceBaseMapper中的分页方法都无法正常起效。 所以,我们必须配置分页插件。

在项目中新建一个配置类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;
    }
}

在配置好后接下来就是通用分页实体等等的编写及接口的开发。

二、分页实体的编写

1、先定义一个统一接收前端的通用分页实体PageQuery

给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 <T> Page<T> toMpPage(OrderItem ... items){
        // 1.分页条件
        Page<T> 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 <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc){
        OrderItem orderItem=new OrderItem();
        //排序方式
        orderItem.setAsc(isAsc);
        //排序字段
        orderItem.setColumn(defaultSortBy);
        return this.toMpPage(orderItem);
    }

    public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
        return toMpPage("create_time", false);
    }

    public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {
        return toMpPage("update_time", false);
    }
}
2、再编写一些具体前端需要传的分页需要的类来继承PageQuery
@Data
public class EmployeePageQueryDTO extends PageQuery implements Serializable {

//    //页码
//    private Long pageNo;
//    //每页显示记录数
//    private Long pageSize;

    //员工姓名
    private String name;
    
}
3、定义通用返回的VO类--》PageResult,返回给前端

因为分页查询所需的就3个属性,总记录数,总页数,分页查询得到的数据,所以这个是统一的VO类

/**
 * 封装分页查询结果
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {

    private Long total; //总记录数

    private Long pages; //总页数

    private List records; //当前页数据集合

}

三、开发接口

1、controller

controller中的方法基本没有什么影响,该怎么写就怎么写,这里提供两种通过接口传参数的案例

    /**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("员工分页查询")
    public Result<PageResult>page(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<PageResult> page(Long page, Long pageSize, Integer status) {
        PageResult pageResult = orderService.pageQueryUser(page, pageSize, status);
        return Result.success(pageResult);
    }
2、serviceI
public interface EmployeeService extends IService<Employee> {

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

}
public interface OrderService extends IService<Orders> {

    /**
     * 历史订单分页查询
     * @param pageNum
     * @param pageSize
     * @param status   订单状态 1待付款 2待接单 3已接单 4已完成 5已取消
     * @return
     */
    PageResult pageQueryUser(Long pageNum, Long pageSize, Integer status);

}
3、serviceImpl

两种不同的接口传到service参数在Impl有两种不同写法,实际上就是一种基本的,但是我之前在PageQuery分页实体类里面写了对应的便捷方法

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper,Employee> implements EmployeeService {

    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //使用mybatisPlus自带的分页插件
        //mybatisX里面默认添加的分页插件和该插件只能存在一个,如果想转换必须导包
        //mybatisX里面的属性为int
        //mybatisPlus里面的属性为long

        // 1.构建分页条件
        Page<Employee> page = employeePageQueryDTO.toMpPageDefaultSortByCreateTimeDesc();

        // 2.分页查询
        Page<Employee> p=lambdaQuery()
                .like(employeePageQueryDTO.getName() != null,Employee::getName, employeePageQueryDTO.getName())
                .page(page);

        // 3.调用插件获得数据
        //获得总的记录数
        long total = p.getTotal();
        //获得总的页数
        long pages = p.getPages();
        //获得当前页数据集合
        List<Employee> records = p.getRecords();

        // 4.返回封装好的分页结果
        return new PageResult(total,pages,records);
    }

}

 在上面这个Impl里面我使用了之前已经PageQuery分页实体类封装的方法来创建分页条件

@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper,Orders> 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<Orders> page = Page.of(pageNum, pageSize);

        OrdersPageQueryDTO ordersPageQueryDTO=new OrdersPageQueryDTO();
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
        ordersPageQueryDTO.setStatus(status);

        // 分页条件查询
        Page<Orders>p=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<Orders> ordersList = p.getRecords();
        List<OrderVO> list = new ArrayList();

        // 查询出订单明细,并封装入OrderVO进行响应
        if (ordersList!=null&& ordersList.size()>0){
            for (Orders orders : ordersList) {
                Long orderId = orders.getId();//订单id

                // 查询订单明细
//                List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(orderId);
                QueryWrapper<OrderDetail> OrderDetailWrapper = new QueryWrapper<>();
                OrderDetailWrapper.lambda().eq(OrderDetail::getOrderId, orderId);
                List<OrderDetail> 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<Orders> page = Page.of(pageNum, pageSize);

// 分页条件查询
        Page<Orders>p=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<Orders> ordersList = p.getRecords();

        return new PageResult(p.getTotal(),p.getPages(),list);
         // 1.构建分页条件
        Page<Employee> page = employeePageQueryDTO.toMpPageDefaultSortByCreateTimeDesc();

        // 2.分页查询
        Page<Employee> p=lambdaQuery()
                .like(employeePageQueryDTO.getName() != null,Employee::getName, employeePageQueryDTO.getName())
                .page(page);

        // 3.调用插件获得数据
        //获得总的记录数
        long total = p.getTotal();
        //获得总的页数
        long pages = p.getPages();
        //获得当前页数据集合
        List<Employee> 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的注入,实际操作 还是要注入的

 4、mapper

mapper里面之前mybatis写的分页查询功能,当然是删掉了或注释掉了

@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {

    //    Page<Employee> pageQueuery(EmployeePageQueryDTO employeePageQueryDTO);

}

四、Page

该类继承了 IPage 类,实现了 简单分页模型 如果你要实现自己的分页模型可以继承 Page 类或者实现 IPage 类,可参考官方文档:分页插件 | MyBatis-Plus

下面给出这个的一些属性,方便使用方法的时候调用对应需要的方法:

属性名类型默认值描述
recordsListemptyList查询数据列表
totalLong0查询列表总记录数
sizeLong10每页显示条数,默认 10
currentLong1当前页
ordersListemptyList排序字段信息,允许前端传入的时候,注意 SQL 注入问题,可以使用 SqlInjectionUtils.check(...) 检查文本
optimizeCountSqlbooleantrue自动优化 COUNT SQL 如果遇到 jSqlParser 无法解析情况,设置该参数为 false
optimizeJoinOfCountSqlbooleantrue自动优化 COUNT SQL 是否把 join 查询部分移除
searchCountbooleantrue是否进行 count 查询,如果只想查询到列表不要查询总记录数,设置该参数为 false
maxLimitLong单页分页条数限制
countIdStringxml 自定义 count 查询的 statementId 也可以不用指定在分页 statementId 后面加上 _mpCount 例如分页 selectPageById 指定 count 的查询 statementId 设置为 selectPageById_mpCount 即可默认找到该 SQL 执行

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乄bluefox

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值