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

Spring JPQL中如何给SIZE函数加条件统计未删除的Dock?

解决方案:无需原生查询,JPQL可实现需求

你的需求完全可以通过JPQL实现,不需要切换到原生SQL。问题出在SIZE(tw.docks)会直接统计实体关联集合中的所有元素,不受JOIN子句条件的影响,所以之前加ON d.isDeleted = false无法改变统计结果。

下面提供两种可行的JPQL写法:

方法一:子查询统计符合条件的Dock数量

这种方式逻辑直观,通过子查询单独统计当前TimeWindow下未被删除的Dock数量:

@Query("""
    SELECT tw FROM TW tw
    JOIN tw.docks d
    WHERE d.id = :dockId
    AND d.isDeleted = false
    AND tw.status <> 'DELETED'
    AND (SELECT COUNT(d2) FROM TW tw2 JOIN tw2.docks d2 WHERE tw2.id = tw.id AND d2.isDeleted = false) = 1
""")
List<TW> findByDockIdAndValidDockCountOne(@Param("dockId") Long dockId);
  • 首先通过JOIN tw.docks d并过滤d.id = :dockId和d.isDeleted = false,确保TimeWindow关联了指定的未删除Dock;
  • 子查询部分专门统计当前TimeWindow下所有未删除的Dock数量,判断是否等于1。

方法二:GROUP BY + HAVING条件计数

利用分组和条件计数来实现需求,避免子查询:

@Query("""
    SELECT tw FROM TW tw
    LEFT JOIN tw.docks d ON d.isDeleted = false
    WHERE EXISTS (SELECT 1 FROM tw.docks d2 WHERE d2.id = :dockId AND d2.isDeleted = false)
    AND tw.status <> 'DELETED'
    GROUP BY tw.id
    HAVING COUNT(d) = 1
""")
List<TW> findByDockIdAndValidDockCountOne(@Param("dockId") Long dockId);
  • LEFT JOIN tw.docks d ON d.isDeleted = false只关联未删除的Dock;
  • EXISTS子句确保当前TimeWindow确实关联了指定的未删除Dock;
  • GROUP BY tw.id按TimeWindow分组后,COUNT(d)就是该TimeWindow下未删除的Dock数量,通过HAVING判断是否等于1。

补充说明

  • 原查询中的LEFT JOIN因为后续WHERE d.id = :dockId的限制,实际会被优化为INNER JOIN,所以直接用INNER JOIN语义更清晰;
  • 两种写法都不需要依赖原生SQL,完全符合JPQL规范,Hibernate可以正常解析执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:21:07