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

DetachedCriteria多投影时如何仅返回单列解决IN查询列数报错

问题根因

报错触发的直接原因是IN子查询语法强制要求子查询返回结果仅包含1列,你当前定义的criteriaAndamento同时配置了max("data")和groupProperty("processo")两个投影,生成的SQL会返回两列数据,和主查询id单列做匹配时直接触发数据库语法错误。
如果直接移除max("data")投影,虽然能解决列数不匹配问题,但会丢失「按processo分组取最新日期对应记录」的核心聚合逻辑,查询结果不符合预期。

修复方案

采用两层嵌套DetachedCriteria实现,把聚合计算放到关联子查询的匹配条件里,外层用于IN匹配的子查询仅返回processo单列,既保留聚合逻辑,又满足IN子查询的列数要求:

// 内层聚合子查询:按processo维度匹配,计算每个processo符合日期过滤条件的最大data值
DetachedCriteria maxDateQuery = DetachedCriteria.forClass(Andamento.class, "innerA")
        .setProjection(Projections.max("innerA.data"))
        // 日期过滤条件放在内层,保证聚合计算的是符合筛选要求的日期,同时用参数占位符避免SQL注入
        .add(Restrictions.sqlRestriction("DATE_FORMAT(innerA.`data`, '%d/%m/%Y') like concat(?, '%')",
                filter.getFilterValue().toString(), StandardBasicTypes.STRING))
        // 关联外层同processo的记录
        .add(Restrictions.eqProperty("innerA.processo", "outerA.processo"));

// 外层子查询:仅返回processo列(对应主查询要匹配的id),单列投影满足IN语法要求
DetachedCriteria criteriaAndamento = DetachedCriteria.forClass(Andamento.class, "outerA")
        .setProjection(Projections.property("outerA.processo").as("id"))
        // 匹配:记录的data等于该processo下的最大日期,即最新记录
        .add(Subqueries.propertyEq("outerA.data", maxDateQuery));

// 主查询正常关联即可,不会再触发列数不匹配错误
criteria.add(Property.forName("id").in(criteriaAndamento));
注意事项
  • 原代码直接拼接用户输入的filter.getFilterValue()到SQL语句中存在SQL注入风险,上述示例已经改成用?占位符传参的写法,从根源规避注入问题。
  • 子查询必须加不同的表别名(示例里的innerA/outerA),否则Hibernate解析属性时会出现字段归属歧义,导致关联逻辑错误。
  • 这种嵌套写法兼容Hibernate 3.X及以上所有版本,不需要升级框架就能直接使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:03:25