利用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;
}
相关文章
|
6月前
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
1219 1
Spring boot 使用mybatis generator 自动生成代码插件
|
6月前
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
293 1
|
7月前
|
SQL Java 数据安全/隐私保护
发现问题:Mybatis-plus的分页总数为0,分页功能失效,以及多租户插件的使用。
总的来说,使用 Mybatis-plus 确实可以极大地方便我们的开发,但也需要我们理解其工作原理,掌握如何合适地使用各种插件。分页插件和多租户插件是其中典型,它们的运用可以让我们的代码更为简洁、高效,理解和掌握好它们的用法对我们的开发过程有着极其重要的意义。
757 15
|
10月前
|
XML SQL Java
十二、MyBatis分页插件
十二、MyBatis分页插件
329 17
|
10月前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
407 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
11月前
|
SQL Java 数据库连接
【潜意识Java】深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
2012 1
|
11月前
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
1331 6
|
2月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
202 1
|
2月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
226 1
|
3月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案