如何基于起始元素位置实现Spring Boot+JPA的自定义元素分页?
在Spring Boot + Hibernate中基于起始位置和数量实现JpaRepository分页(含自定义排序)
问题核心是你混淆了PageRequest.of(page, size)中page参数的含义——它代表从0开始的页码,底层会自动计算偏移量为page * size,这就是你得到第7-9条数据的原因(2*3=6,从第7条开始取3条)。
要实现基于起始位置(offset)和数量(limit)的分页,无需编写原生查询,利用Spring Data JPA提供的Pageable接口能力即可解决:
1. 构建正确的分页参数
使用PageRequest.ofSize(size).withOffset(offset)来创建包含起始位置、数量和排序规则的Pageable实例,其中:
offset:起始元素位置(从0开始计数,对应你需求中的起始位置2)size:要返回的元素数量- 配合
withSort()添加自定义排序规则
示例代码:
// 起始位置2,数量3,按指定字段降序排序 Pageable pageable = PageRequest.ofSize(3) .withOffset(2) .withSort(Sort.by("any sort").descending());
2. 调用JpaRepository的查询方法
JpaRepository自带的findAll(Pageable pageable)方法会根据传入的参数生成包含OFFSET和LIMIT的SQL,只会加载需要的目标数据,不会产生冗余:
public interface PersonRepository extends JpaRepository<Person, Long> {} // 在业务逻辑中调用 List<Person> targetPersons = personRepository.findAll(pageable);
完整示例(Controller层)
修改接口参数,直接接收offset和排序相关参数,替代原有的页码参数:
@GetMapping("/persons") List<Person> findEveryone( @RequestParam(required = false, defaultValue = "0") long offset, @RequestParam(required = false, defaultValue = "10") int size, @RequestParam(required = false, defaultValue = "id") String sortField, @RequestParam(required = false, defaultValue = "asc") String sortDir) { Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortField); Pageable pageable = PageRequest.ofSize(size).withOffset(offset).withSort(sort); return personRepository.findAll(pageable); }
低版本兼容说明
如果你的Spring Boot版本低于2.2(对应Spring Data Commons低于2.2),可以通过自定义Pageable实现类来设置偏移量:
// 兼容低版本的写法 Sort sort = Sort.by("any sort").descending(); Pageable pageable = new PageRequest(0, size, sort) { @Override public long getOffset() { return offset; // 传入你的起始位置 } };
内容的提问来源于stack exchange,提问作者Rustem Zamaliev
相关产品推荐
相关产品推荐

