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

Spring Data JPA基于滚动查询及运算优先级返回意外结果

问题解决思路

1. 方法名派生查询的逻辑错误修复

你遇到的第一个问题是Spring Data JPA方法名解析的逻辑优先级偏差:原方法名findByHeadOfIdAndAddedDateNotNullOrDurationNotNull会被解析为:

WHERE (head_of_id = ?1 AND added_date IS NOT NULL) OR (duration IS NOT NULL)

这就导致只要满足duration IS NOT NULL,无论headOfId是否匹配都会返回数据;即便你的测试数据中duration为NULL,错误的分组逻辑也可能因added_date非空出现意外匹配。

修正方案:在方法名中用括号明确条件分组,确保headOfId与(addedDateNotNull OR durationNotNull)为AND关系:

interface ItemRepository : JpaRepository<Item, Long> {
    fun findByHeadOfIdAnd(AddedDateNotNullOrDurationNotNull)(
        headOfId: Long,
        position: ScrollPosition,
        pageable: Pageable
    ): Window<Item>
}

该方法名会生成正确的SQL:

WHERE head_of_id = ?1 AND (added_date IS NOT NULL OR duration IS NOT NULL)

此时传入headOfId=0L时,因head_of_id=0不匹配测试数据的1000L,不会返回该记录。

2. 滚动查询不支持@Query的替代方案

Spring Data JPA目前不支持返回Window<T>的自定义@Query注解查询,因为滚动查询需要框架处理ScrollPosition的游标逻辑,自定义字符串查询无法集成该机制。如果需要更灵活的查询逻辑,可使用Specification:

步骤1:让Repository继承JpaSpecificationExecutor

interface ItemRepository : JpaRepository<Item, Long>, JpaSpecificationExecutor<Item> {
    fun findAll(spec: Specification<Item>, position: ScrollPosition, pageable: Pageable): Window<Item>
}

步骤2:构建查询Specification

fun buildItemQuerySpec(headOfId: Long): Specification<Item> {
    return Specification { root, _, cb ->
        // 构建headOfId匹配条件
        val headOfIdPred = cb.equal(root.get<Long>("headOf.id"), headOfId)
        // 构建addedDate非空或duration非空的OR条件
        val addedDatePred = cb.isNotNull(root.get<ZonedDateTime>("addedDate"))
        val durationPred = cb.isNotNull(root.get<Int>("duration"))
        val orPred = cb.or(addedDatePred, durationPred)
        // 组合AND条件
        cb.and(headOfIdPred, orPred)
    }
}

步骤3:调用查询

// 示例调用
val spec = buildItemQuerySpec(0L)
val window = itemRepository.findAll(spec, ScrollPosition.offset(), Pageable.ofSize(10))

这样既可以实现自定义查询逻辑,又能支持滚动查询的Window返回类型。

内容的提问来源于stack exchange,提问作者four-eyes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:28:12