@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
相关产品推荐
相关产品推荐

