HQL查询报错unexpected token: *该如何修复?
错误原因
报错unexpected token: *核心原因有两点:
- 你调用的是
em.createQuery()方法,该方法会将传入语句按HQL(Hibernate面向实体的查询语言)规则解析,HQL原生不支持SELECT *的通配符写法,所有查询字段必须明确指定。 - 你编写的语句本质是Oracle风格原生SQL,包含大量HQL不识别的语法:比如数据库专属的
ROWNUM关键字、直接关联物理表的JOIN写法、两层嵌套子查询结构,均不符合HQL解析规范。
修复方案
优先采用原生SQL方案,改动成本最低,无需调整现有实体映射:
- 第一步:将
em.createQuery()替换为em.createNativeQuery(),该方法会将语句直接传给数据库做原生SQL解析,不会走HQL语法校验。 - 第二步:修正SQL里的两处隐性问题:
- 把内层子查询的
SELECT *改成SELECT id,内层派生表仅返回id单个字段,无需用通配符查询,同时可避免不同数据库下*带来的字段匹配问题 - 给内层嵌套的派生表加别名,Oracle要求所有FROM后的子查询必须显式声明别名,否则会触发SQL语法错误
- 把内层子查询的
修正后可直接运行的SQL如下:
SELECT DISTINCT h.cod_1 AS cod1, h.cod_2 AS cod2, h.cod_3 AS cod3, w.stato AS stato FROM workflow w JOIN hist_1 h ON h.id = w.id_riga AND h.dt_perio_rif = '202111' WHERE w.id_report = '1' AND w.id = ( SELECT id FROM ( SELECT w2.id FROM workflow w2 WHERE w2.id_riga = w.id_riga AND w2.id_report = '1' ORDER BY w2.update_date DESC ) t WHERE ROWNUM = 1 );
对应的Java代码写法参考:
// 第二个参数可传入自定义结果DTO、实体类实现结果自动映射,不传则返回List<Object[]>类型结果 Query query = em.createNativeQuery(上述SQL语句, YourResultDTO.class);
如果必须用HQL实现,需做以下改造,整体改动成本较高:
- 确认
Workflow和Hist1两个实体的关联映射配置,HQL的JOIN基于实体关联属性实现,不能直接写物理表名+ON关联条件 - 移除所有
SELECT *写法,所有查询字段显式声明 - 移除SQL里的
ROWNUM关键字,HQL不支持数据库专属分页关键字,取第一条数据需要在创建Query后调用query.setMaxResults(1)实现 - 调整嵌套子查询结构,HQL对子查询位置有严格限制,仅能出现在SELECT、WHERE子句中,部分版本不支持多层嵌套子查询。
内容的提问来源于stack exchange,提问作者GHOST DEVELOPER
相关产品推荐
相关产品推荐

