重写SimpleJpaRepository的findAll方法实现分页改造

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

这重写SimpleJpaRepository的findAll方法实现分页改造

最近项目中提出一个需求,在查询的页码大于总页码数时,将查询页改成最后一页。
如> 总页数10,查询页数传的是11时,查询结果时间返回第10页数据。
主要是为了防止有多人操作时,删和查同时进行的问题。

背景;
项目中关于数据库查询都是使用JPA的接口
分页查询使用JPA中的findAll 传参 Pageable
查看源码不难发现
JPA findAll 操作实际上分为以下几步

  1. 获取pageNumber 和pageSize 获取limit 的范围【start,end】
  2. 执行语句 select 查询字段 from table where 条件 limit start,end 获取到具体字段数据
  3. 执行 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 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值