利用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;
}
相关文章
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
829 1
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
2074 6
|
SQL Java 数据库连接
【潜意识Java】深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
3136 1
|
SQL Java 数据库连接
【潜意识Java】深入理解MyBatis,从基础到高级的深度细节应用
本文详细介绍了MyBatis,一个轻量级的Java持久化框架。内容涵盖MyBatis的基本概念、配置与环境搭建、基础操作(如创建实体类、Mapper接口及映射文件)以及CRUD操作的实现。此外,还深入探讨了高级特性,包括动态SQL和缓存机制。通过代码示例,帮助开发者更好地掌握MyBatis的使用技巧,提升数据库操作效率。总结部分强调了MyBatis的优势及其在实际开发中的应用价值。
615 1
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
885 2
|
存储 SQL Java
Java反射读取注解信息
Java反射读取注解信息
202 0
|
JSON 安全 Java
|
IDE Java 编译器
java的反射与注解
java的反射与注解
206 0
|
安全 Java API
Java中的反射(通过反射获取类的结构、invoke方法、获取注解)
Java中的反射(通过反射获取类的结构、invoke方法、获取注解)
|
前端开发 Java 编译器
Java的第十六篇文章——枚举、反射和注解(后期再学一遍)
Java的第十六篇文章——枚举、反射和注解(后期再学一遍)