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

如何将通用Blaze Persistence查询包装为子查询以按ROW_NUMBER()=1筛选?

如何将通用Blaze Persistence查询包装为子查询以按ROW_NUMBER()=1筛选?

我明白你的痛点——在泛型场景下手动绑定实体属性完全不可行,fromEntitySubquery确实是解决这个问题的正确方向,只是它的用法需要稍微调整一下。你之前的尝试把内部查询的逻辑结构放错了位置,下面是正确的实现方式:

return criteriaBuilder
    // 1. 外层查询:基于实体子查询构建,自动映射传入的entityClass类型
    .fromEntitySubquery(entityClass, "groupedEntity")
        // 2. 定义子查询(对应原有的完整查询逻辑)
        .from(entityClass, "entityData")
        .innerJoinOn(ChangeData.class, "changes")
            .on("changes.id").eqExpression("entityData.id")
        .end()
        .select("entityData") // 保留原实体数据的投影
        .select("ROW_NUMBER() OVER (PARTITION BY changes.id ORDER BY changes.sequence DESC)", "rn")
        .select("changes.id", "changes_id")
        .select("changes.sequence")
        .selectNew(entityObjectBuilder)
    // 3. 外层查询添加过滤条件:只保留rn=1的最新版本记录
    .where("rn").eq(1)
    // 4. 选择外层的实体结果,无需手动绑定属性
    .select("groupedEntity")
    // 若需要子查询中的其他投影字段,直接引用别名即可
    .select("groupedEntity.changes_id")
    .select("groupedEntity.sequence")
    .getQuery();

关键逻辑说明:

  • fromEntitySubquery的核心价值就是自动将子查询中的实体投影映射到外层的实体别名,完全不需要手动绑定实体的任何属性,完美适配你需要的泛型场景。
  • 你之前的错误是把外层的过滤条件写在了子查询内部,正确的流程是:先在子查询中计算出rn字段,再在外层查询中通过where("rn").eq(1)筛选出每个changes.id对应的最新版本记录。
  • 外层查询可以直接引用子查询中定义的所有别名(包括自定义的rn、changes_id等),操作方式和普通实体查询完全一致。

如果你的需求只是获取每个分组下的最新实体数据,还可以简化成更简洁的版本:

return criteriaBuilder
    .fromEntitySubquery(entityClass, "groupedEntity")
        .from(entityClass, "entityData")
        .innerJoinOn(ChangeData.class, "changes")
            .on("changes.id").eqExpression("entityData.id")
        .end()
        .select("entityData")
        .select("ROW_NUMBER() OVER (PARTITION BY changes.id ORDER BY changes.sequence DESC)", "rn")
    .where("rn").eq(1)
    .select("groupedEntity")
    .getQuery();

备注:内容来源于stack exchange,提问作者fishi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:23:04