在持久层、Java集合运算里面,分页是很常见的操作。
用户对分页最直白的需求是怎样的?可以参考浏览器的搜索结果展示。页码从1开始,第几页就展示第几页的内容。
使用下来发现有些分页是从零开始,有些从一开始。有些可以用页码跳到指定页,有些需要计算offset,因此将所有情况都捋一捋,并且记录互相转换方式以便查询。
数据
id |
---|
1 |
2 |
3 |
4 |
MySQL limit offset
1 | select id from xxx limit 2 offset 1 |
Spring JPA Pageable
Spring Controller支持从url的size、page、sort等参数构建Pageable,通过JPA请求MySQL。那么用户需要的每页数量、页码是怎样传递的呢?
size,page,sort的值会直接用于生成Pageable,也就是和PageRequest.of(page, size)一样。
需要注意,page=0查的是第1页,page=1查到的结果已经是第2页了。
比“MySQL limit offset”方便的是,页码帮算好了,不需要计算offset值。
Java Stream
某些场景下需要从数据库捞全量数据,在内存中做分页。
使用Java Stream的skip、limit方法可以方便地对数据做切片。skip的参数类似“MySQL limit offset”的offset值。因为Pageable的页码已经减一,所以这里只要skip “每页数量 x 页码”即可。
从Pageable到Stream切片转换的例子如下:1
2
3IntStream.range(0, 20)
.skip(pageable.getPageSize() * (pageable.getPageNumber()))
.limit(pageable.getPageSize()).forEach(System.out::println);