利用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;
}
相关文章
|
1月前
|
SQL XML Java
8、Mybatis-Plus 分页插件、自定义分页
这篇文章介绍了Mybatis-Plus的分页功能,包括如何配置分页插件、使用Mybatis-Plus提供的Page对象进行分页查询,以及如何在XML中自定义分页SQL。文章通过具体的代码示例和测试结果,展示了分页插件的使用和自定义分页的方法。
8、Mybatis-Plus 分页插件、自定义分页
|
3天前
|
SQL Java 数据库连接
解决mybatis-plus 拦截器不生效--分页插件不生效
本文介绍了在使用 Mybatis-Plus 进行分页查询时遇到的问题及解决方法。依赖包包括 `mybatis-plus-boot-starter`、`mybatis-plus-extension` 等,并给出了正确的分页配置和代码示例。当分页功能失效时,需将 Mybatis-Plus 版本改为 3.5.5 并正确配置拦截器。
解决mybatis-plus 拦截器不生效--分页插件不生效
|
6天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
6天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
16天前
|
Arthas Java 测试技术
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
Java字节码文件、组成、详解、分析;常用工具,jclasslib插件、阿里arthas工具;如何定位线上问题;Java注解
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
|
12天前
|
Java 程序员 编译器
Java的反射技术reflect
Java的反射技术允许程序在运行时动态加载和操作类,基于字节码文件构建中间语言代码,进而生成机器码在JVM上执行,实现了“一次编译,到处运行”。此技术虽需更多运行时间,但广泛应用于Spring框架的持续集成、动态配置及三大特性(IOC、DI、AOP)中,支持企业级应用的迭代升级和灵活配置管理,适用于集群部署与数据同步场景。
|
7天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
1月前
|
前端开发 Java 数据库连接
一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这篇文章总结了Java面试中的十个问题,包括Spring事务传播机制、Spring事务失效条件、Bean自动装配方式、Spring、Spring MVC和Spring Boot的区别、Spring MVC的工作流程和主要组件、Spring Boot的自动配置原理和Starter概念、嵌入式服务器的使用原因,以及MyBatis的优缺点。
|
1月前
|
Java 数据库 Spring
MyBatisPlus分页插件在SpringBoot中的使用
这篇文章介绍了如何在Spring Boot项目中配置和使用MyBatis-Plus的分页插件,包括创建配置类以注册分页拦截器,编写测试类来演示如何进行分页查询,并展示了测试结果和数据库表结构。
MyBatisPlus分页插件在SpringBoot中的使用
|
1月前
|
XML Java 数据库连接
Mybatis java.lang.NumberFormatException: For input string: "1,2" 问题处理
【8月更文挑战第9天】Mybatis java.lang.NumberFormatException: For input string: "1,2" 问题处理