Java实现后端分页

  分页操作在开发中可以说是最基本的操作,特别是在做各种后台管理系统的时候,不可能一次性查询一千条、一万条数据。

这时候就需要进行分页操作。那么在Java后端当中是如何实现分页的呢?下面就来聊一聊Java后端分页。

Java分页原理

  首先说说分页的原理。有几个名词需要解释一下,数据总数,每页显示的记录数,当前页,总页数。

.1.假设某张表中总条数: total

.2.每页显示记录数:pageSize

.3.当前页:pageNum

.4.总页数:pages

第一步:页面当中需要传入两个数据,每页显示的记录数和当前页;

第二步:查询某张表的总数赋值给total;

第三步:计算总页数 总页数 = Math.ceil(总条数 * 1.0 / 每页显示记录数);

第四步:封装结果返回数据。

说明:总条数 * 1.0表示把一个整数转换为double类型的数据进行计算,否则两个整数相除,计算结果就是一个整数会舍弃掉小数部分。

Math.ceil()表示向上取整。举例每页显示6条数据,如果总共有8条数据,应该显示为2页,而不是1页。

示例一:如果每页显示5条,总数据分别为1516,19该显示为多少条数据。

Math.ceil(15 * 0.1 / 5) 3Math.ceil(16 * 0.1 / 5) 4Math.ceil(19 * 0.1 / 5) 4。符合要求,重点需要理解当最后一页的数据不满一页时,也需要单独显示为一页。

Mysql分页原理

Mysql中分页需要使用一个关键字limit,语法如下

Select * from limit offset,size;

后面跟一个参数或者是两个参数。只跟一个参数表示从第一条记录开始,取size条记录。

如果跟两个参数,第一个参数offset表示偏移量,第二个参数size表示获取的记录数。

下面来做一个简单的测试,建表语句如下,

DROP TABLE IF EXISTS page_test;

CREATE TABLE `page_test` (

 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',

 `name` varchar(16) DEFAULT NULL COMMENT '名称',

 `age` int(11) DEFAULT '0' COMMENT '年龄',

 PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='分页测试表';

测试数据如下,

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('1', '测试名称1', '1');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('2', '测试名称2', '2');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('3', '测试名称3', '3');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('4', '测试名称4', '4');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('5', '测试名称5', '5');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('6', '测试名称6', '6');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('7', '测试名称7', '7');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('8', '测试名称8', '8');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('9', '测试名称9', '9');

INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('10', '测试名称10', '10');

下面进行查询测试:

SELECT * FROM page_test order by id asc limit 0,3;

 

SELECT * FROM page_test order by id asc limit 3;

 

上面两个查询语句结果一致。

SELECT * FROM page_test order by id asc limit 1, 3;

 

SELECT * FROM page_test order by id asc limit 3,3;

SELECT * FROM page_test order by id asc limit 6,3;

 

从查询的结果中可以看出,如果每页显示3条数据,limit 0,3表示查询第一页;limit 3,3表示查询第二页;limit 6, 3表示查询第3页。

因此可以推导出一个公式:查询起始位置 = (当前页 - 1) * 每页显示记录数。然后每次分页查询时,动态传入limit后面的两个参数即可。

 

Java代码实现示例

@Getter
@Setter
@NoArgsConstructor
public class PageReSult<T> {

   // 数据总数
   private Integer total;

   // 当前页码
   private Integer pageNum;

   // 每页显示记录数
   private Integer pageSize;

   // 总页数
   private Integer pages;

   // 列表数据
   private List<T> data;
}

说明: Set/get/构造函数使用的是Lombok实现。

 

分页思路如下

.a.获取页面中传递的参数;

.b.查询总条数;

.c.计算mysql中的起始查询位置,查询当前页的数据;

.d.获取当前页的数据;

.e.封装查询结果;

.f.返回数据;

 

具体示例代码如下

@WebServlet("/pageTest")

public class PageTestApi extends HttpServlet {

    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 获取分页参数

        String pageNumStr = req.getParameter("pageNum");

        String pageSizeStr = req.getParameter("pageSize");

        // 将分页参数转换为整数

        Integer pageNum = Integer.parseInt(pageNumStr);

        Integer pageSize = Integer.parseInt(pageSizeStr);

        System.out.println("pageNum--->" + pageNum + ";pageSize=" + pageSize);

        // 查询总条数

        String countSql = " SELECT count(*) total FROM page_test ";

        PreparedStatement stmt = null;

        Integer total = 0;

        PageReSult pageReSult = new PageReSult();

        // 使用工具类获取数据库连接

        try (Connection conn = JDBCUtils.getConnection();){

            // 获取数据库操作对象 prepareStatement 可以预编译sql防止sql注入

            stmt = conn.prepareStatement(countSql);

            // 执行查询

            ResultSet rs = stmt.executeQuery();

            // 获取查询结果

            if(rs.next()){

                total = rs.getInt("total");

            }

            System.out.println("total--->" + total);

 

            // 计算 mysql limit 查询的起始位置

            int start = (pageNum - 1) * pageSize;

// 查询分页数据,最好按照某个字段进行排序,否则查询结果可能会不准确

            String selectSql = " SELECT * FROM page_test order by id asc limit ?,?";

            stmt = conn.prepareStatement(selectSql);

            stmt.setObject(1, start);

            stmt.setObject(2, pageSize);

 

            rs = stmt.executeQuery();

            List<EntityTest> data = new ArrayList<>();

            // 获取查询结果集

            while (rs.next()){

                EntityTest entityTest = new EntityTest();

                entityTest.setId(rs.getLong("id"));

                entityTest.setName(rs.getString("name"));

                entityTest.setAge(rs.getInt("age"));

                data.add(entityTest);

            }

 

            // 计算总页数

            Integer pages = (int)Math.ceil(total * 1.0 / pageSize);

            // 封装查询结果

            pageReSult.setTotal(total);

            pageReSult.setPages(pages);

            pageReSult.setPageNum(pageNum);

            pageReSult.setData(data);

            pageReSult.setPageNum(pageNum);

        } catch (SQLException e) {

            throw new RuntimeException("分页查询错误!");

        }

        // 使用工具类返回查询结果

        CommonResult.success(resp, pageReSult);

    }

}

 

每页查询3条数据,测试结果如下:

第一页数据,重点看id1,2,3.

 

第二页数据,id4,5,6

 

 

如果每页查询5条数据,查询第二页结果也正确。到此Java后端分页查询功能全部实现。有其他建议的小伙伴,欢迎留言讨论。

posted @ 2024-03-20 17:01  一只爱阅读的程序员  阅读(1563)  评论(0编辑  收藏  举报