这重写SimpleJpaRepository的findAll方法实现分页改造
最近项目中提出一个需求,在查询的页码大于总页码数时,将查询页改成最后一页。
如> 总页数10,查询页数传的是11时,查询结果时间返回第10页数据。
主要是为了防止有多人操作时,删和查同时进行的问题。
背景;
项目中关于数据库查询都是使用JPA的接口
分页查询使用JPA中的findAll 传参 Pageable
查看源码不难发现
JPA findAll 操作实际上分为以下几步
- 获取pageNumber 和pageSize 获取limit 的范围【start,end】
- 执行语句 select 查询字段 from table where 条件 limit start,end 获取到具体字段数据
- 执行 select count(id) from table where 条件 获取页数和总记录数
如果不重写findAll方法,我们需要自己在每次分页查询前先进行count运算,计算出当前请求的页码是不是超过总页数,如果超过将请求页码改为最后一页。
这样做有几个弊端:
- 每次做分页都要进行count,代码量增加,麻烦,还有可能忘记处理。当前项目要求所有分页查业务数据的地方都做处理
- JPA的findAll分页查询的方法本身就有count查询,自己在service里再写count,导致多次进行SQL查询,无疑会降低查询效率
首先看一下SimpleJpaRepository 源码
public Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable) {
// 获取查询条件和查询语句
TypedQuery<T> query = getQuery(spec, pageable);
// 获取查询结果、总页数、总记录数封装成Page返回
return isUnpaged(pageable) ? new PageImpl<T>(query.getResultList())
: readPage(query, getDomainClass(), pageable, spec);
}
修改分页操作,重点看readPage函数,实际上重写的是readPage的函数
/**
* Reads the given {@link TypedQuery} into a {@link Page} applying the given {@link Pageable} and
* {@link Specification}.
*
* @param query must not be {@literal null}.
* @param domainClass must not be {@literal null}.
* @param spec can be {@literal null}.
* @param pageable can be {@literal null}.
* @return
*/
protected <S extends T> Page<S> readPage(TypedQuery<S> query, final Class<S> domainClass, Pageable pageable,
@Nullable Specification<S> spec) {
// 此处设置limit范围
if (pageable.isPaged()) {
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
}
return PageableExecutionUtils.getPage(query.getResultList(), pageable,
() -> executeCountQuery(getCountQuery(spec, domainClass)));
}
query.getResultList() 查询获取sql语句的数据结果
先查询结果,再执行executeCountQuery 进行count运算获取总页数和总记录数
query对应实现类 AbstractProducedQuery
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setFirstResult(int startPosition) {
getProducer().checkOpen();
if ( startPosition

博客介绍了如何通过重写Spring Data JPA的SimpleJpaRepository的findAll方法来实现分页查询优化,当请求页码超过总页数时自动跳转到最后一页。详细分析了JPA的分页查询流程,并给出代码实现,包括调整查询顺序,计算总页数,以及在必要时更新Pageable对象。最后,通过创建自定义的PageSimpleJpaRepository并使用@EnableJpaRepositories注解指定为基类,实现了全局的分页查询改造。
最低0.47元/天 解锁文章
3万+

被折叠的 条评论
为什么被折叠?



