SpringBoot SQL查询指定字段报错及修正查询正确性验证
问题分析与修正
原查询报错原因
原查询开启nativeQuery=true执行原生SQL,但返回类型是实体类Oas2ChannelPatient,而SQL仅查询了externalId和externalIdType两个字段。Spring Data JPA尝试将结果映射到实体类时,找不到channelPatientMapId等其他必填字段的对应值,因此抛出InvalidDataAccessResourceUsageException。
更新后的查询存在的问题
更新后的查询有多处错误,无法正常运行:
- 语法冲突:
NEW ChannelPatientSearchDto.ChannelExternalIdDTO(...)是JPQL专属的构造器语法,但同时设置了nativeQuery=true,原生SQL不支持这种写法。 - 表/字段名不匹配:原数据库表为
tb_patient_map,查询中却写了tb_oas_2_channel_patient_map;数据库字段是patientId,查询中误用了oasPatientId。 - 参数绑定错误:方法参数标注
@Param("patientId"),但查询中用:oasPatientId引用参数,名称不匹配导致参数无法绑定。 - DTO类引用错误:用户定义的DTO是
ChannelPatientDto.ChannelExternalIdDTO,查询中却引用了不存在的ChannelPatientSearchDto.ChannelExternalIdDTO。 - 注解滥用:
@Modifying仅用于更新/删除操作,查询语句不需要该注解。
正确的查询写法
方法一:JPQL+DTO构造器(推荐)
@Query(value = "SELECT NEW com.your.package.ChannelPatientDto.ChannelExternalIdDTO(t.externalId, t.externalIdType) " + "FROM tb_patient_map t " + "WHERE t.patientId = :patientId AND t.channelId = :channelId") List<ChannelPatientDto.ChannelExternalIdDTO> findByPatientIdAndChannelId(@Param("patientId") String patientId, @Param("channelId") int channelId);
注意事项:
- 移除
nativeQuery=true,使用JPQL语法; - 替换
com.your.package为DTO类实际所在的包路径; - 表名、字段名严格与数据库结构保持一致;
- 查询操作无需
@Modifying和@Transactional(特殊业务场景除外)。
方法二:原生SQL+接口投影(适合复杂查询场景)
若需保留原生SQL,可以定义投影接口:
public interface ChannelExternalIdProjection { String getExternalId(); String getExternalIdType(); }
对应查询写法:
@Query(value = "SELECT externalId, externalIdType FROM tb_patient_map " + "WHERE patientId = :patientId AND channelId = :channelId", nativeQuery = true) List<ChannelExternalIdProjection> findByPatientIdAndChannelId(@Param("patientId") String patientId, @Param("channelId") int channelId);
内容的提问来源于stack exchange,提问作者dracile
相关产品推荐
相关产品推荐

