java中实现分页的几种常见方式总结

目录
  • 1. 前言
  • 2. 先说结论
  • 3. 例子
    • 1. 数据库SQL的限制条件(limit、fetch)
    • 2. 使用List集合的截取功能实现
    • 3. 插件PageHelper
  • 总结

1. 前言

无论是自我学习中,还是在工作中,固然会遇到与前端搭配实现分页的功能,发现有几种方式,特此记录一下。

2. 先说结论

  1. 分页功能直接交给前端实现(根据业务场景且仅仅只能用于数据量少的情况)。即后端不做任何数据的限制,直接把全部数据返回给前端,前端通过组件实现分页,筛选等功能。请不要轻视该方式,好处即只需要前后端交互一次。
  2. 使用数据库SQL的限制条件,即给搜索语句加上条件,限制查询出来的数据个数:
    1. mysql数据库是使用 limit n,m 从第n个开始,往后取m个(注 不包括第n个数据)
    2. oracle数据库是使用 OFFSET n ROWS FETCH NEXT m ROWS ONLY 从第n行开始,往后取m行(注 不包括第n行数据)
    3. oracle的可以查看这篇文章:oracle中将数据进行排序之后,获取前几行数据的写法(rownum、fetch方式)
  3. 使用List集合的截取功能实现,即将数据都查到内存中List集合,在内存中找到要的数据。当然有人说这种方式还不如第二点,但请具体情况具体分析,有可能需求要的数据,是从数据库中查询不到的,需要将原始数据查到内存加工处理数据之后得到,才能进行分页处理。(同理,该方法,只能根据需求且数据量少的情况)
  4. 使用优秀的插件PageHelper,真的很不错。

3. 例子

1. 数据库SQL的限制条件(limit、fetch)

先说结论

mysql写法:
SELECT * FROM user2
LIMIT (#{pageNum} - 1) * #{pageSize}, #{pageSize}

oracle写法:
SELECT * FROM user2
OFFSET (#{pageNum} - 1) * #{pageSize} ROWS FETCH NEXT #{pageSize} ROWS ONLY

直接看代码:

@Mapper
public interface PageTestDao {

	// 查数据
	// start:从第几条开始,向后要数据
	// pageSize:一页多少条数据
    List<UserEntity> getUserInfoByParams(@Param("nameParam") String name,
                                         @Param("start") int start,
                                         @Param("pageSize") int pageSize);
	// 返回总条数
    int getCountByParams(@Param("nameParam") String name);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.csdn2.page_test.dao.PageTestDao">

    <sql id="nameCondition">
        <where>
            <if test="nameParam != null and nameParam != ''">
                name like CONCAT('%', #{nameParam}, '%')
            </if>
        </where>
    </sql>

    <select id="getUserInfoByParams" resultType="com.example.csdn2.page_test.entity.UserEntity">
        SELECT * FROM user2
        <include refid="nameCondition" />
        LIMIT #{start}, #{pageSize}
    </select>

    <select id="getCountByParams" resultType="int">
        SELECT COUNT(*) FROM user2
        <include refid="nameCondition" />
    </select>
</mapper>
@Service
@RequiredArgsConstructor
public class PageTestService {

    private final PageTestDao pageTestDao;

    public PageResponse<UserEntity> getPageTest(UserRequest userRequest) {
        final List<UserEntity> userEntityList = pageTestDao.getUserInfoByParams(userRequest.getNameParam(),
                userRequest.getStart(), userRequest.getPageSize());

        final int total = pageTestDao.getCountByParams(userRequest.getNameParam());

        return new PageResponse<>(userEntityList, total);
    }
}
// 若分页的需求很多,可把分页相关的参数抽出来
@Data
public class PageRequest {

    // 第几页
    private int pageNum;

    // 每页几行数据
    private int pageSize;

	// 计算从第几行开始
	// 无论是limit、还是fetch 都是从某一行数据开始,向后取 pageSize 条数据
    public int getStart() {
        if (pageNum <= 0) {
            return 0;
        }
        return (pageNum - 1) * pageSize;
    }
}

// 入参
@EqualsAndHashCode(callSuper = true)
@Data
public class UserRequest extends PageRequest {

    // 搜索参数
    private String nameParam;
}

// 返回实体类,因为分页需要返回总条数,前端好做下标第几页
@Data
@AllArgsConstructor
public class PageResponse<T> {

    private List<T> data;

	// 总条数
    private int total;
}
@RestController
@RequiredArgsConstructor
public class PageTestController {

    private final PageTestService pageTestService;

    @PostMapping("/page-test")
    public PageResponse<UserEntity> getPageTest(@RequestBody UserRequest userRequest){
       return pageTestService.getPageTest(userRequest);
    }
}

2. 使用List集合的截取功能实现

1.先看一下List的截取

// 从第几个下标,到第几个下标
List<E> subList(int fromIndex, int toIndex);
    public void test_ListSub() {
    	// 创建模拟数据,字符串 0-9的集合
        final List<String> list = IntStream.range(0, 10)
                .mapToObj(i -> i + "")
                .collect(Collectors.toList());
        System.out.println(list);
        // 截取从下标0到5的数据
        System.out.println(list.subList(0, 5));
        // 截取从下标3到5的数据
        System.out.println(list.subList(3, 5));
    }

2.回归上述分页例子,代码改成如下:

dao层 不加 limit 条件

  SELECT * FROM user2
  name like CONCAT('%', #{nameParam}, '%')

server层:

 public PageResponse<UserEntity> getPageTestByListSub(UserRequest userRequest) {
        final List<UserEntity> allData = pageTestDao.getUserInfoByParamsNoLimit(userRequest.getNameParam());
        // 下标开始
        final int start = userRequest.getStart();
        // 下标结束
        final int end = start + userRequest.getPageSize();
        // 截取数据
        final List<UserEntity> userEntityList = allData.subList(start, end);

        final int total = pageTestDao.getCountByParams(userRequest.getNameParam());
        return new PageResponse<>(userEntityList, total);
    }

3. 插件PageHelper

1.其实PageHelper官网中有详细的文档以及例子:https://pagehelper.github.io/docs/howtouse/

2.下面例子只是讲其与springboot结合的核心内容,即快速开发

3.引入相关jar包坐标到pom.xml中

<dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>1.3.0</version>
</dependency>

4.dao层的sql不需要加 Limit 条件(因为PageHelper会自动帮忙加的)

  SELECT * FROM user2
  name like CONCAT('%', #{nameParam}, '%')

5.service层修改如下:

   public PageInfo<UserEntity> getPageTest(UserRequest userRequest) {
        // 告诉PageHelper数据要从第几页,每页多少条数据
        // 注:一定要在select查询语句之前使用该方法,否则无效
        PageHelper.startPage(userRequest.getPageNum(), userRequest.getPageSize());

        // 查询sql
        final List<UserEntity> userEntityList = pageTestDao.getUserInfoByParamsNotLimit(userRequest.getNameParam());

        // 返回dto,使用插件自带的PageInfo
        return new PageInfo<>(userEntityList);

		// 上述逻辑还可以简写为:
		// return PageHelper.startPage(userRequest.getPageNum(), userRequest.getPageSize())
            // .doSelectPageInfo(() -> pageTestDao.getUserInfoByParamsNotLimit(userRequest.getNameParam()));
    }

6.结果如下(与之前查询结果一致,没问题):

{
    "total": 9,
    "list": [
        {
            "name": "4a",
            "pwd": "D"
        },
        {
            "name": "5a",
            "pwd": "E"
        },
        {
            "name": "6a",
            "pwd": "F"
        }
    ],
    "pageNum": 2,
    "pageSize": 3,
    "size": 3,
    "startRow": 4,
    "endRow": 6,
    "pages": 3,
    "prePage": 1,
    "nextPage": 3,
    "isFirstPage": false,
    "isLastPage": false,
    "hasPreviousPage": true,
    "hasNextPage": true,
    "navigatePages": 8,
    "navigatepageNums": [
        1,
        2,
        3
    ],
    "navigateFirstPage": 1,
    "navigateLastPage": 3
}

7.为什么说该插件很优秀呢查看PageInfo的返回参数,核心内容:

	// 当前页
    private int pageNum;
    // 每页的数量
    private int pageSize;
    // 当前页的数量
    private int size;

    // 总记录数
    private long total;
    // 总页数
    private int pages;
    // 结果集
    private List<T> list;

 	// 以下内容都是其自动帮生成的
 	// 对于前端来说极其友好,前端分页功能的全部参数都包含了
    // 前一页的页码
    private int prePage;
    // 下一页的页码
    private int nextPage;
    // 是否为第一页
    private boolean isFirstPage = false;
    // 是否为最后一页
    private boolean isLastPage = false;
    // 是否有前一页
    private boolean hasPreviousPage = false;
    // 是否有下一页
    private boolean hasNextPage = false;
    // 导航条上的第一页的页码
    private int navigateFirstPage;
    // 导航条上的第一页的页码
    private int navigateLastPage;

8.查看PageHelper执行了什么sql语句

总结

到此这篇关于java中实现分页的几种常见方式的文章就介绍到这了,更多相关java实现分页方式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java实现分页显示效果

    本文实例为大家分享了java实现页显示效果的具体代码,供大家参考,具体内容如下 效果图如下: 实现步骤: 1.创建实体User.class,参考代码如下: public class User { private String name; private int age; private String gender; public String getName() { return name; } public void setName(String name) { this.name = nam

  • Java分页工具类及其使用(示例分享)

    Pager.java package pers.kangxu.datautils.common; import java.io.Serializable; import java.util.List; /** * * <b> 分页通用类 </b> * * @author kangxu * @param <T> * */ public class Pager<T> implements Serializable { /** * */ private stati

  • Java实现分页代码

    在项目中,分页是一个项目中必不可少的,它可以防止我们从数据库中进行大量数据查询时速度变慢,提高我们的查询效率. 1.定义分页模型:PageModel package com.common.page; import java.util.List; /** * 封装分页信息 * @author Administrator * */ public class PageModel<E> { //结果集 private List<E> list; //查询记录数 private int to

  • 如何用java实现分页查询

    1.基本思路 我现阶段的分页查询的实现是基于sql语句的. select * from user where id limit a, b 构造出相应的a和b就可以查询出想要的数据,在显示在页面上.重点是要构造出当前的页数,就要封装一个javaBean,存储有关分页的基本属性. 这样只需在service层计算想要的页数,并封装基本的信息,在查询出来显示在前端就可以了. 2.具体实现 1.定义JavaBean public @Data class PageBean<T> implements Se

  • java中List分页的几种方法介绍

    目录 1.根据入参带分页参数进行sql查询分页 2.对所有list根据分页参数分页 3.PageHelper分页 1.根据入参带分页参数进行sql查询分页 Criteria criteria = new Criteria(); //将dataAuto转成 factoryId brandId seriesId 等查询条件 String dataAuth = ""; TypeCaseHelper.dataAuto(criteria, dataAuth); // 设置分页信息 ExtPage

  • java分页工具类的使用方法

    说明:曾经在网上看过花样繁多的分页,很多都号称如何通用,但很多时候往往不尽如人意:有在分页类中还加入URL地址信息的,有在分页类中还进行分页动作处理(此动作完全属于操作数据库方面的事情)的.现在好了,经本人总结与提炼: 无论你是否自己手动分页,还是借助了框架进行分页.此工具类都可以帮助你达到稳定的分页效果(包括导航页码功能),而且使用方法也相对简单:好了,废话少说,代码如下: package test.dao; import java.util.List; /** * 用于分页的工具类 * @a

  • Java实现简单的分页功能

    本文实例为大家分享了Java实现分页功能的具体代码,供大家参考,具体内容如下 不用根据改变SQL的形式去查询; 直接查询所有的数据,根据页码自动显示数据; 分页对象 public class PageUtils implements Serializable { /** * */ private static final long serialVersionUID = -5247614532234782640L; public final static String PAGE = "page&q

  • java中实现分页的几种常见方式总结

    目录 1. 前言 2. 先说结论 3. 例子 1. 数据库SQL的限制条件(limit.fetch) 2. 使用List集合的截取功能实现 3. 插件PageHelper 总结 1. 前言 无论是自我学习中,还是在工作中,固然会遇到与前端搭配实现分页的功能,发现有几种方式,特此记录一下. 2. 先说结论 分页功能直接交给前端实现(根据业务场景且仅仅只能用于数据量少的情况).即后端不做任何数据的限制,直接把全部数据返回给前端,前端通过组件实现分页,筛选等功能.请不要轻视该方式,好处即只需要前后端交

  • Java中枚举类型的一种使用方式

    今天改同事的代码发现同事的代码中有大量的if else语句.很不美观而且可读性太差. 因为需要给前端一个key,value的列表.这个列表写死.然而同事的代码. 放几张图,大家自己感受.我都不知道以后这个api咋维护,新增一个工站,减少一个工站. 果然新的任务新增4个工站,好吧,开始给代码装扮一下. 首先,写一个枚举类. package com.smartflow.common.enumpackage; /** * @author :tao * @date :Created in 2020/8/

  • 一文详解Python中实现单例模式的几种常见方式

    目录 Python 中实现单例模式的几种常见方式 元类(Metaclass): 装饰器(Decorator): 模块(Module): new 方法: Python 中实现单例模式的几种常见方式 元类(Metaclass): class SingletonType(type): """ 单例元类.用于将普通类转换为单例类. """ _instances = {} # 存储单例实例的字典 def __call__(cls, *args, **kwa

  • Java中关于 null 的几种处理方式详解

    对于 Java 程序员来说,空指针⼀直是恼⼈的问题,我们在开发中经常会受到 NullPointerException 的异常.Java 的发明者也承认这是⼀个巨⼤的设计错误.那么关于 null ,你应该知道下⾯这⼏件事情来有效的了解 null ,从⽽避免很多由 null 引起的错误. ⼤⼩写敏感 ⾸先,null 是 Java 中的 关键字 ,像是 public.static.final.它是⼤⼩写敏感的,你不能将 null 写 成 Null 或 NULL,编辑器将不能识别它们然后报错. 这个问题

  • Java中匿名类的两种实现方式

    使用匿名内部类课使代码更加简洁.紧凑,模块化程度更高.内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到.然而这个不是我说的重点,我说的很简单,就是匿名内部类的两种实现方式:第一种,继承一个类,重写其方法:第二种,实现一个接口(可以是多个),实现其方法.下面通过代码来说明: public class TestAnonymousInterClass{ public static void main(String args[]){ TestAnonymousInterCl

  • JAVA中 Spring定时器的两种实现方式

    目前有两种流行Spring定时器配置:Java的Timer类和OpenSymphony的Quartz. 1.Java Timer定时 首先继承java.util.TimerTask类实现run方法 import java.util.TimerTask; public class EmailReportTask extends TimerTask{ @Override public void run() { ... } } 在Spring定义 ... 配置Spring定时器 <bean id=&quo

  • java中分组统计的三种实现方式

    平时工作中,很多时候都会用到对数据进行分组操作,例如一个学生对象,有班级.名字.性别.分数等,需要按班级分组统计,该怎么操作呢?一个合理的算法可以提升不少效率. 大家看一下下面的案例: //下面是初始化的数据 List<Student> list = new ArrayList<Student>(); Student student1 = new Student("李四1", "女", "一班"); Student stu

  • Java项目开发中实现分页的三种方式总结

    目录 前言 使用 1.SpringDataJPA分页 2.MyBatis分页 3.Hutools工具类分页 总结 前言 Java项目开发中经常要用到分页功能,现在普遍使用SpringBoot进行快速开发,而数据层主要整合SpringDataJPA和MyBatis两种框架,这两种框架都提供了相应的分页工具,使用方式也很简单,可本人在工作中除此以外还用到第三种更方便灵活的分页方式,在这里一同分享给大家. 使用 主要分为SpringDataJPA分页.MyBatis分页.Hutools工具类分页几个部

  • Java中break的第三种用法说明

    在Java中,break语句有三种用法,第一种是用于终止switch语句中的语句序列,第二种是用于退出循环,然而第三种是用作goto语句的"文明"形式! 我们知道,goto语句会破坏程序的结构,所以我们一般不会去使用这种功能.但是在某些情况下,goto语句对于流程控制很有价值并且结构合法. 比如当退出深度嵌套的一系列循环时,goto语句很好用.虽然Java中保留了goto关键字,但是没有goto语句,也没有任何用到这个关键字的地方,所以为了能够使用类似像goto语句这样的功能,Java

随机推荐