Spring Data JPA原生查询转DTO时PostgreSQL语法错误求助
问题解决:PostgreSQL语法错误(syntax error at or near "(")
报错信息
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "(" Position: 26
相关代码与环境
Repository层代码
@Query(value = "select new AgendamentoDTO(a.id, a.data, s.nome, p.nome, pro.nome) " + "from agendamento a " + "join pacientes p on p.id = a.paciente_id " + "join profissionais pro on pro.id = a.profissional_id " + "join servico s on s.id = a.servico_id", nativeQuery = true) List<AgendamentoDTO> agendamentos3();
DTO类代码
@Data @NoArgsConstructor public class AgendamentoDTO { private Integer id; private String data; private String servico; private String paciente; private String profissional; public AgendamentoDTO(Integer id, String paciente, String data, String profissional, String servico) { this.id = id; this.data = data; this.servico = servico; this.paciente = paciente; this.profissional = profissional; } }
使用环境
- SpringData 2.7.0
- 数据库:PostgreSQL
问题原因与解决办法
原因
开启nativeQuery = true后,执行的是PostgreSQL原生SQL,但你在语句里用了JPQL独有的new AgendamentoDTO(...)构造对象语法,PostgreSQL无法识别该语法,直接触发报错。
解决办法
方案1:关闭原生查询(推荐)
删除nativeQuery = true,让Spring Data执行JPQL查询,JPQL支持直接通过构造方法实例化DTO:
@Query(value = "select new AgendamentoDTO(a.id, p.nome, a.data, pro.nome, s.nome) " + "from Agendamento a " + "join a.paciente p " + "join a.profissional pro " + "join a.servico s") List<AgendamentoDTO> agendamentos3();
注意两点:
- 把数据库表名替换为实体类名(比如
agendamento改成Agendamento),用实体类属性名代替数据库列名; - 构造参数顺序必须和DTO构造方法完全匹配——你的DTO构造方法参数顺序是
id, paciente, data, profissional, servico,所以JPQL里要对应写成a.id, p.nome, a.data, pro.nome, s.nome,之前的顺序错误,就算语法修复也会导致字段赋值混乱。
方案2:保留原生查询,手动映射结果
如果必须用原生SQL,去掉new AgendamentoDTO(...),直接查询字段并设置别名,让Spring Data自动映射到DTO:
@Query(value = "select a.id, p.nome as paciente, a.data, pro.nome as profissional, s.nome as servico " + "from agendamento a " + "join pacientes p on p.id = a.paciente_id " + "join profissionais pro on pro.id = a.profissional_id " + "join servico s on s.id = a.servico_id", nativeQuery = true) List<AgendamentoDTO> agendamentos3();
确保DTO的字段名和SQL里的别名完全一致,Spring Data就能自动把查询结果赋值到DTO对象中。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

