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

@Formula字段无法被客户端识别,countDistinct查询报属性找不到异常

解决Hibernate Criteria查询中无法识别@Formula字段的问题

你碰到的这个IllegalArgumentException其实很典型——Hibernate的Criteria API没法直接识别用@Formula标注的虚拟字段。这个fix字段并不是实体的持久化属性,只是Hibernate在生成SQL时动态计算出来的,所以你用position.get("fix")去引用它,JPA的元模型(ManagedType)根本找不到这个属性,自然会报错。

给你两种可行的解决办法:

方法一:直接在Criteria中拼接字段(推荐)

既然@Formula的作用是拼接三个字段,那我们可以跳过@Formula,直接在Criteria查询里完成拼接操作,这样完全符合Criteria API的规范:

@SuppressWarnings({"unchecked", "rawtypes"})
public long getCountDistinctPositions() {
    Session session = sessionFactory.openSession();
    CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
    CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class);
    Root<Position> position = criteriaQuery.from(Position.class);
    
    // 逐层拼接longitude、latitude、update_time三个字段
    Expression<String> combinedFields = criteriaBuilder.concat(
        criteriaBuilder.concat(position.get("longitude"), position.get("latitude")),
        position.get("update_time")
    );
    
    Expression<Long> countDistinct = criteriaBuilder.countDistinct(combinedFields);
    criteriaQuery.select(countDistinct);
    
    Long result = session.createQuery(criteriaQuery).getSingleResult();
    session.close();
    return result;
}

方法二:改用HQL查询(如果你想保留@Formula)

如果你一定要保留实体类中的@Formula字段,可以改用HQL查询——HQL能够识别@Formula定义的虚拟字段,而不需要依赖JPA的元模型:

@SuppressWarnings({"unchecked", "rawtypes"})
public long getCountDistinctPositions() {
    Session session = sessionFactory.openSession();
    // 直接通过实体类的fix字段进行count distinct查询
    String hql = "select count(distinct p.fix) from Position p";
    Long result = (Long) session.createQuery(hql).getSingleResult();
    session.close();
    return result;
}

⚠️ 注意:这里要确保数据库支持concat函数(比如MySQL用concat,Oracle可以用||或者concat函数),如果你的数据库不支持,需要调整@Formula里的拼接语法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:52:57