利用java反射解决Mybatis Pagehelper插件联表查询分页不准确的问题(一)

简介: 利用java反射解决Mybatis Pagehelper插件联表查询分页不准确的问题

前言


反射可以获取任何一个已知名称的类中定义的属性,不论它是公有还是私有!使用反射你会发现原来java可以如此灵活,你不用再无穷无尽地写循环、定义变量,它会让你的代码简洁大方,耦合性更低。我本身刚刚接触到反射,希望通过一个分页功能的实现和大家一起去学习应用反射,在编程的不归路上越走越远。


背景


很多人在mybatis开发中都喜欢使用pagehelper当做自己的分页插件,但是这个插件在使用过程中一直存在一个问题——多表关联一对多的情况下分页会出现不准确的情况,出现这种情况的原因是当你的查询语句主表和附表之间是一对多的关系时,当sql语句查询完成后mybatis会以主表为主将附表信息封装到你定义的主表对应的字段中。本人也曾尝试去仔细阅读pageheloer的api文档,但是找来找去耽误了很长时间也没找到具体行之有效的方法。索性自己封装一个pageutil,总体来说效果不错~


使用框架与结构的定义


在案例中我们使用的前端框架是vue,这里不做过多的介绍,如果大家感兴趣我会在后期写一篇使用vue-cli搭建vue项目的博客。后端是springboot。


实例

首先封装一个pageBO,用来存放返回前端的数据

@Data
public class PageBO {
    private int size;//list长度
    private int total;//总查询数
    private int startRow;//开始条数
    private int endRow;//结束条数
    private int firstPage;//第一页页码
    private int lastPage;//最后一页页码
    private int pages;//页数
    private int[] navigatepageNums;//页码数组
    private int pageNum;//当前页码
    private int pageSize;//每页数据量
    Object list;//数据列表
}


pageUtil源码:

import com.easy.xbo.PageBO;
import org.apache.poi.ss.formula.functions.T;
import java.lang.reflect.Method;
import java.util.List;
public class PageUtil {
    public static PageBO getPageBOData(Object service,Object param) throws  Exception{
        PageBO pageBO=new PageBO();
        Class Pageclass=service.getClass();
        Class Paramclass=param.getClass();
        Method PagemethodSelectCount=Pageclass.getDeclaredMethod("selectCount",Paramclass);
        //可以通过Method类的invoke方法调用类方法
        //查询总数,此时注意需要传递两个参数,第一个是方法所在的类,第二个是方法需要的参数 
        //invoke方法第一个参数是固定的,是方法所在类,第二个是可选的,是方法所需参数
        int count=Integer.parseInt(PagemethodSelectCount.invoke(service,param)+"");
        Method ParammethodGet=Paramclass.getDeclaredMethod("getWhere");
        Object where=ParammethodGet.invoke(param);
        Class Whereclass=where.getClass();
        //第几页
        Method WheremethodPage=Whereclass.getDeclaredMethod("getPage");
        int page=Integer.parseInt(WheremethodPage.invoke(where)+"");
        //每页条数
        Method WheremethodRows=Whereclass.getDeclaredMethod("getRows");
        int pageSize=Integer.parseInt(WheremethodRows.invoke(where)+"");
        //计算本页从哪一条数据开始
        int startRow=(page-1)*pageSize;
        Method WheremethodStartrow=Whereclass.getDeclaredMethod("setStartrow",int.class);
        WheremethodStartrow.invoke(where,startRow);
        //计算页数
        int pages=count/pageSize;
        if(count%pageSize>0){
            pages++;
        }
        //存放页码的数组
        int [] NavigatepageNums=new int[pages];
        for(int i=1;i<=pages;i++){
            NavigatepageNums[i-1]=i;
        }
        pageBO.setTotal(count);
        pageBO.setStartRow(startRow+1);
        pageBO.setFirstPage(1);
        pageBO.setPages(pages);
        pageBO.setLastPage(pages);
        pageBO.setNavigatepageNums(NavigatepageNums);
        pageBO.setPageSize(pageSize);
        pageBO.setPageNum(page);
        Method PagemethodSelectPage=Pageclass.getDeclaredMethod("selectPage",Paramclass);
        Object pagelist=  PagemethodSelectPage.invoke(service,param);
        pageBO.setList(pagelist);
        pageBO.setSize(((List)pagelist).size());
        int endRow=startRow+pageBO.getSize();
        pageBO.setEndRow(endRow);
        return pageBO;
    }
}

Object 类型的 service 中必须有两个方法:一个是 selectCount 用来查询分页的total,也就是所有符合查询条件的数据总数;一个是 selectPage 这个方法查询具体数据。

Object 类型的 param 包含两个参数:一个是where;一个是xdo。(具体结构参照)

然后就是对反射的使用(具体参照)

以上是公用部分的代码


下面举个栗子~~:

公司与员工的关系,一个公司有多个员工,属于一对多的关系,这里插一句lombok很好用,有兴趣的小伙伴可以了解一下


CompanyDO源码:

package com.easy.xdo;
import lombok.Data;
@Data
public class CompanyDO {
  //演示公司类
  private String id;
  private String name;
  private String address;
  private List<EmployeDO> employes;
}
相关文章
|
15天前
|
SQL Java 数据库连接
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
96 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
5天前
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
15天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
108 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
54 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
24天前
|
搜索推荐 Java 数据库连接
Java|在 IDEA 里自动生成 MyBatis 模板代码
基于 MyBatis 开发的项目,新增数据库表以后,总是需要编写对应的 Entity、Mapper 和 Service 等等 Class 的代码,这些都是重复的工作,我们可以想一些办法来自动生成这些代码。
30 6
|
24天前
|
Java 程序员 调度
Java|PageHelper 怎么自作主张帮我分页?
没有调用 PageHelper.startPage,查询怎么也被自动分页了?
13 2
|
2月前
|
SQL XML Java
springboot整合mybatis-plus及mybatis-plus分页插件的使用
这篇文章介绍了如何在Spring Boot项目中整合MyBatis-Plus及其分页插件,包括依赖引入、配置文件编写、SQL表创建、Mapper层、Service层、Controller层的创建,以及分页插件的使用和数据展示HTML页面的编写。
springboot整合mybatis-plus及mybatis-plus分页插件的使用
|
1月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
16 0
|
存储 SQL Java
Java反射读取注解信息
Java反射读取注解信息
70 0