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

按Id排序分页时不同页码出现同一实体的问题排查

分页查询重复实体问题的解决方案

问题描述

执行分页查询时,不同current_page返回结果中出现同一个CardsKanBanEntidade实体,数据库中ID无重复且不为null,切换为按ID排序后问题仍存在。

问题原因

核心原因是关联查询产生笛卡尔积:在Specification中使用root.join("kanbanLane")进行关联查询时,如果LanesKanBanEntidade与CardsKanBanEntidade的关联关系触发重复匹配(比如单条Card对应多条关联Lane记录),会生成重复的Card实体行。JPA分页是基于原始查询结果的行数进行分页,而非去重后的实体数,因此重复行被分到不同页面,导致同一实体出现在多页中。

解决方案

方案1:添加Distinct去重

在查询中强制开启去重,确保返回的实体唯一。修改过滤逻辑,在Specification中设置query.distinct(true):

Specification<CardsKanBanEntidade> filter = Specification.where((root, query, cb) -> {
    // 开启去重,消除重复实体行
    query.distinct(true);
    return cb.equal(root.join("kanbanLane").get("passoId"), lane_id);
});

Specification<CardsKanBanEntidade> lojaFilter = Specification.where(null);
if (lojas != null && !lojas.isEmpty()) {
    lojaFilter = lojaFilter.and((root, query, cb) -> root.get("loja").in(lojas));
}

filter = filter.and(lojaFilter);

方案2:用Exists子查询替代Join(更高效)

避免使用Join产生笛卡尔积,改用Exists子查询实现关联过滤,从根源上消除重复行:

Specification<CardsKanBanEntidade> filter = Specification.where((root, query, cb) -> {
    Subquery<LanesKanBanEntidade> subquery = query.subquery(LanesKanBanEntidade.class);
    Root<LanesKanBanEntidade> laneRoot = subquery.from(LanesKanBanEntidade.class);
    // 子查询匹配目标lane,并关联当前Card
    subquery.select(laneRoot)
            .where(cb.equal(laneRoot.get("passoId"), lane_id),
                   cb.equal(root.get("kanbanLane"), laneRoot));
    return cb.exists(subquery);
});

Specification<CardsKanBanEntidade> lojaFilter = Specification.where(null);
if (lojas != null && !lojas.isEmpty()) {
    lojaFilter = lojaFilter.and((root, query, cb) -> root.get("loja").in(lojas));
}

filter = filter.and(lojaFilter);

验证建议

  • 开启SQL日志,查看生成的SQL语句是否存在重复行
  • 确认LanesKanBanEntidade与CardsKanBanEntidade的关联关系是否符合业务逻辑(@ManyToOne应确保单Card对应单Lane,若实际是一对多则需检查数据或业务规则)

内容的提问来源于stack exchange,提问作者Davi Américo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:53:16