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

PostgreSQL下JPA原生查询排除主键报错,求实体类调整方案

问题原因分析

你碰到的这个org.postgresql.util.PSQLException: The column name id was not found in this ResultSet错误,核心原因在于:你的PublisherInfoResponseEntity被标记为@Entity,且包含带@Id注解的id字段。JPA在映射原生查询结果到实体类时,默认会要求结果集中必须存在主键对应的列,但你的SQL查询里并没有选择id列,因此触发了这个异常。


解决方案1:将实体类改为DTO(推荐方案)

既然这个类是用来接收查询结果的响应实体,而非需要持久化的数据库实体,最合理的做法是把它改成普通DTO类,移除JPA实体相关注解,再调整结果集映射规则。

步骤1:重构PublisherInfoResponseEntity类

移除@Entity、@Table、@Id注解,并补充需要接收的annual表字段,同时添加全参构造函数用于结果映射:

public class PublisherInfoResponseEntity { 
    private String publisher_name; 
    private String contact_name; 
    private String contact_phone; 
    private String contact_email; 
    private String managed_services; 
    // 补充接收annual表的字段
    private Integer customers;
    private Integer employees;
    private BigDecimal revenue;

    // 全参构造函数(用于结果集映射)
    public PublisherInfoResponseEntity(String publisher_name, String contact_name, String contact_phone, 
                                       String contact_email, String managed_services, Integer customers, 
                                       Integer employees, BigDecimal revenue) {
        this.publisher_name = publisher_name;
        this.contact_name = contact_name;
        this.contact_phone = contact_phone;
        this.contact_email = contact_email;
        this.managed_services = managed_services;
        this.customers = customers;
        this.employees = employees;
        this.revenue = revenue;
    }

    // 无参构造函数(按需添加)
    public PublisherInfoResponseEntity() {}

    // getters and setters
}

步骤2:调整@NamedNativeQuery和@SqlResultSetMapping

把原来的@EntityResult替换为@ConstructorResult,指定DTO的构造函数与查询列的映射关系,同时修复SQL语句末尾的多余逗号:

@NamedNativeQueries(value = { 
    @NamedNativeQuery( 
        name = "getPublisherInfoList", 
        query = "SELECT publisher.publisher_name,publisher.contact_name,publisher.contact_email,publisher.contact_phone,publisher.managed_services,\n" + 
                "annual.customers,annual.employees,annual.revenue\n" + 
                "FROM publisher_portal.publisher_informations publisher JOIN publisher_portal.publisher_annual annual\n" + 
                "ON publisher.publisher_name=annual.publisher_name", 
        resultSetMapping = "PublisherInfoResponseMappings" 
    ), 
    @NamedNativeQuery( 
        name = "getPublisherByName", 
        query = "SELECT publisher.publisher_name,publisher.contact_name,publisher.contact_email,publisher.contact_phone,\n" + 
                "publisher.managed_services,annual.customers,annual.employees,annual.revenue\n" + 
                "FROM publisher_portal.publisher_informations publisher JOIN publisher_portal.publisher_annual annual\n" + 
                "ON publisher.publisher_name=annual.publisher_name where publisher.publisher_name= :publisherName", 
        resultSetMapping = "PublisherInfoResponseMappings" 
    ) 
}) 
@SqlResultSetMapping(name = "PublisherInfoResponseMappings", 
    classes = { 
        @ConstructorResult(
            targetClass = PublisherInfoResponseEntity.class,
            columns = {
                @ColumnResult(name = "publisher_name", type = String.class),
                @ColumnResult(name = "contact_name", type = String.class),
                @ColumnResult(name = "contact_email", type = String.class),
                @ColumnResult(name = "contact_phone", type = String.class),
                @ColumnResult(name = "managed_services", type = String.class),
                @ColumnResult(name = "customers", type = Integer.class),
                @ColumnResult(name = "employees", type = Integer.class),
                @ColumnResult(name = "revenue", type = BigDecimal.class)
            }
        )
    }
)
// 注意:这个映射注解可以放在任意一个JPA实体类上,不需要绑定到DTO

解决方案2:保留实体类的妥协方案(不推荐)

如果因为特殊需求必须让PublisherInfoResponseEntity作为JPA实体存在,那你必须在SQL查询中包含id列,即使你不需要它:

SELECT publisher.id, publisher.publisher_name,publisher.contact_name,publisher.contact_email,publisher.contact_phone,publisher.managed_services,
annual.customers,annual.employees,annual.revenue
FROM publisher_portal.publisher_informations publisher JOIN publisher_portal.publisher_annual annual
ON publisher.publisher_name=annual.publisher_name

同时在@FieldResult中添加@FieldResult(name = "id", column = "id"),让JPA能找到主键列。但这种方法会返回你不需要的id字段,仅作为特殊场景下的妥协方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:07:50