4、PageHelper分页查询

1、MyBatis的分页方式:

逻辑分页与物理分页

1、逻辑分页:使用MyBatis自带的RowBounds进行分页,是一次性查询很多数据,然后再在结果中检索分页的数据。这样做弊端是需要消耗大量的内存、有内存溢出的风险、对数据库压力较大。

2、物理分页:使用分页插件PageHelper或者自己写sql分页(limit),是从数据库查询指定条数的数据,弥补了一次性全部查出的所有数据的种种缺点,比如需要大量的内存,对数据库查询压力较大等问题。

2、PageHelper的原理:

PageHelper是MyBatis提供的分页插件;首先是在Mybatis里面配置了分页拦截器(PageInterceptor),即在执行相关Sql之前会拦截做一点事情;通过setLocalPage()方法,将分页信息保存在当前线程中。查询方法与之处于同一个线程中,共享ThreadLocal中的数据。selectlist查询之后赋值给的List list。这个list是Page 类型。再将list放到PageInfo<>中即可。

3、PageHelper分页实现:

(1)、建工程:

建立Springboost工程;

(2)、改POM:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!--SpringBoot框架web项目起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!--lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <optional>true</optional>
        </dependency>

        <!--PageHelper插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.2</version>
        </dependency>
    </dependencies>

(3)、写YML:

server:
  port: 8081

spring:
  application:
    name: pagehelperdemo
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource    #当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver    #mysql驱动包
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
    druid:
      test-while-idle: false  #关闭空闲检测

mybatis:
  mapperLocations: classpath:mapper/*.xml    #resources下建mapper包

(4)、业务类:

    //实现类 
   @Autowired
    private PageDemoMapper pageDemoMapper;

    /**
     * PageHelper分页查询
     * @Param pageNum:页数
     * @Param pageSize:每页显示的条目
     * */
    @Override
    public PageInfo<PageDemo> selectPage(Integer pageNum , Integer pageSize) {
        log.info("页数:"+pageNum);
        log.info("每页显示的条目:"+pageSize);
        //查询数据库的时候会自动加上limit
        //PageDemoMapper: List<PageDemo> selectAllDemo();
        return PageHelper.startPage(pageNum, pageSize)
                .doSelectPageInfo(() -> pageDemoMapper.selectAllDemo());
    }    

 4、自定义分页工具类:

import com.github.pagehelper.PageInfo;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;


public class PageHelperUtil {

    /**
     * @Description: @description: 自定义分页工具类
     * @param pageNum 当前页
     * @param pageSize 每页显示的数目
     * @param list 总数据
     */
    public static <T> PageInfo<T> initPageInfo(int pageNum, int pageSize, List<T> list) {
        if(ObjectUtils.isEmpty(list)){
            PageInfo<T> pageInfo = new PageInfo<>(new ArrayList<>());
            // 当前页
            pageInfo.setPageNum(pageNum);
            // 每页的数量
            pageInfo.setPageSize(pageSize);
            return pageInfo;
        }
        int total = list.size();
        // 默认如果当前页小于0则为第一页
        pageNum = pageNum <= 0 ? 1 : pageNum;
        // 默认如果当前页大于最大的页数为当前页
        pageNum = pageNum > (total + pageSize - 1) / pageSize ? (total + pageSize - 1) / pageSize : pageNum;
        // 将需要分页的数组进行截取处理
        int fromIndex = 0;
        int toIndex = 0;
        if (total / pageSize == 0 && total % pageSize > 0) {
            // 表示当前数据只有一页
            fromIndex = 0;
            toIndex = total;
        } else if (total / pageSize >= 1 && total % pageSize >= 0) {
            // 超过一页
            fromIndex = (pageNum - 1) * pageSize;
            toIndex = pageNum * pageSize >= total ? total : pageSize * pageNum;
        }
        List<T> tempList = list.subList(fromIndex, toIndex);// 真正需要分页显示的数据
        PageInfo<T> pageInfo = new PageInfo<>(tempList);// 结果集(每页显示的数据)
        pageInfo.setPageNum(pageNum);// 当前页
        pageInfo.setPageSize(pageSize);// 每页的数量
        pageInfo.setSize(tempList.size());// 当前页的数量
        pageInfo.setStartRow(0);// 当前页面第一个元素在数据库中的行号
        pageInfo.setEndRow(tempList.size() > 0 ? tempList.size() - 1 : 0);// 当前页面最后一个元素在数据库中的行号
        pageInfo.setTotal(total);// 总记录数
        pageInfo.setPages((total + pageSize - 1) / pageSize);// 总页数
        calcNavigatepageNums(pageInfo);// 计算导航页
        calcPage(pageInfo);// 计算前后页,第一页,最后一页
        judgePageBoudary(pageInfo);// 判断页面边界
        if (pageInfo.getList() == null) {
            pageInfo.setList(new ArrayList<>());
        }
        return pageInfo;
    }

    /**
     * 计算导航页
     */
    private static <T> void calcNavigatepageNums(PageInfo<T> pageInfo) {
        int pages = pageInfo.getPages();
        int navigatePages = pageInfo.getNavigatePages();
        int pageNum = pageInfo.getPageNum();
        // 当总页数小于或等于导航页码数时
        if (pages <= navigatePages) {
            pageInfo.setNavigatepageNums(new int[pages]);
            for (int i = 0; i < pages; i++) {
                pageInfo.getNavigatepageNums()[i] = i + 1;
            }
        } else { // 当总页数大于导航页码数时
            pageInfo.setNavigatepageNums(new int[navigatePages]);
            int startNum = pageNum - navigatePages / 2;
            int endNum = pageNum + navigatePages / 2;

            if (startNum < 1) {
                startNum = 1;
                // (最前navigatePages页
                for (int i = 0; i < navigatePages; i++) {
                    pageInfo.getNavigatepageNums()[i] = startNum++;
                }
            } else if (endNum > pages) {
                endNum = pages;
                // 最后navigatePages页
                for (int i = navigatePages - 1; i >= 0; i--) {
                    pageInfo.getNavigatepageNums()[i] = endNum--;
                }
            } else {
                // 所有中间页
                for (int i = 0; i < navigatePages; i++) {
                    pageInfo.getNavigatepageNums()[i] = startNum++;
                }
            }
        }
    }

    /**
     * 计算前后页,第一页,最后一页
     */
    private static <T> void calcPage(PageInfo<T> pageInfo) {
        int[] navigatepageNums = pageInfo.getNavigatepageNums();
        int pageNum = pageInfo.getPageNum();
        int pages = pageInfo.getPages();
        if (navigatepageNums != null && navigatepageNums.length > 0) {
            pageInfo.setFirstPage(navigatepageNums[0]);
            pageInfo.setLastPage(navigatepageNums[navigatepageNums.length - 1]);
            if (pageNum > 1) {
                pageInfo.setPrePage(pageNum - 1);
            }
            if (pageNum < pages) {
                pageInfo.setNextPage(pageNum + 1);
            }
        }
    }

    /**
     * 判定页面边界
     */
    private static <T> void judgePageBoudary(PageInfo<T> pageInfo) {
        int pageNum = pageInfo.getPageNum();
        int pages = pageInfo.getPages();
        pageInfo.setIsFirstPage(pageNum == 1);
        pageInfo.setIsLastPage(pageNum == pages);
        pageInfo.setHasPreviousPage(pageNum > 1);
        pageInfo.setHasNextPage(pageNum < pages);
    }

}

 

posted on 2022-06-18 23:50  爱文(Iven)  阅读(482)  评论(0编辑  收藏  举报

导航