You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot WebFlux Kotlin R2DBC 实现suspend分页返回Page对象咨询

Spring WebFlux R2DBC Repository 返回Page分页对象解决方案

报错原因

Spring Data R2DBC 原生不支持在Repository查询方法上直接声明返回Page<T>类型,框架校验时会认为返回类型不符合响应式规范,触发启动报错。

解决方案

1. 调整Repository定义

拆分查询逻辑为两个独立方法,分别查询当前页数据和符合条件的总条数:

interface MemberContactableStatusRepository : ReactiveCrudRepository<MemberContactableStatusEntity, Long> {
    suspend fun findByUserId(userId: Long): MemberContactableStatusEntity?
    // 查询当前页数据
    suspend fun findAllByUserId(userId: Long, pageable: Pageable): List<MemberContactableStatusEntity>
    // 查询符合条件的总记录数
    suspend fun countByUserId(userId: Long): Long
}

2. Service层手动组装Page对象

通过协程并发执行两个查询降低耗时,再用Spring官方提供的PageImpl实现类组装分页对象:

import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageImpl
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service

@Service
class MemberContactableStatusService(
    private val repository: MemberContactableStatusRepository
) {
    suspend fun getPageByUserId(userId: Long, pageable: Pageable): Page<MemberContactableStatusEntity> = coroutineScope {
        // 并发查询提升性能
        val totalCount = async { repository.countByUserId(userId) }
        val records = async { repository.findAllByUserId(userId, pageable) }
        // 组装分页对象
        PageImpl(records.await(), pageable, totalCount.await())
    }
}

可选优化

如果业务不需要返回总记录数、总页数,可改用Slice实现:仅在查询当前页数据时多查1条,根据返回结果数量判断是否存在下一页,可避免count查询带来的性能损耗。


内容的提问来源于stack exchange,提问作者Sehyeon Youn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 08:15:06