PostgreSQL报错:ResultSet未找到id列,JPA查询返回Product实体遇阻
问题分析
你遇到的org.postgresql.util.PSQLException: 此ResultSet中未找到列名id错误,根源在于原生SQL查询返回的字段不全,无法映射到完整的Product实体:
你的仓库方法里写的是select product.name from product ...,只查询了name列,但JPA要把结果转换成Product对象时,需要实体类中定义的所有必要字段(比如id、priceUnit等),结果集里没有id列,自然抛出找不到列的异常。
解决方案
以下是三种可行的解决方式,按需选择:
方式一:修改SQL查询完整的Product字段
把SQL中的select product.name改成select product.*,让结果集包含Product实体对应的所有数据库列,这样JPA就能正确映射成Product对象:
@Repository public interface ProductRepository extends JpaRepository<Product,Integer> { @Query(value = "select product.* from product WHERE product.id NOT IN( select product_id FROM orders WHERE from_date = :fromDate and to_date = :toDate)", nativeQuery = true ) List<Product> findProductsById(@DateTimeFormat(pattern = "yyyy-MM-dd") @Param("fromDate") LocalDate fromDate, @DateTimeFormat(pattern = "yyyy-MM-dd") @Param("toDate") LocalDate toDate); }
方式二:返回部分字段的DTO/投影
如果业务只需要name字段,没必要返回完整的Product实体,可以创建一个DTO类来接收查询结果:
- 创建DTO类:
public class ProductNameDTO { private String name; public ProductNameDTO(String name) { this.name = name; } // getter、setter public String getName() { return name; } public void setName(String name) { this.name = name; } }
- 修改仓库方法的返回类型:
@Repository public interface ProductRepository extends JpaRepository<Product,Integer> { @Query(value = "select product.name from product WHERE product.id NOT IN( select product_id FROM orders WHERE from_date = :fromDate and to_date = :toDate)", nativeQuery = true ) List<ProductNameDTO> findProductsById(@DateTimeFormat(pattern = "yyyy-MM-dd") @Param("fromDate") LocalDate fromDate, @DateTimeFormat(pattern = "yyyy-MM-dd") @Param("toDate") LocalDate toDate); }
方式三:改用JPQL查询(推荐)
用JPQL代替原生SQL,JPA会自动处理实体与数据库表的映射,避免手动写SQL时的字段遗漏问题:
@Repository public interface ProductRepository extends JpaRepository<Product,Integer> { @Query("SELECT p FROM product p WHERE p.id NOT IN (SELECT o.product.id FROM orders o WHERE o.fromDate = :fromDate AND o.toDate = :toDate)") List<Product> findProductsById(@Param("fromDate") LocalDate fromDate, @Param("toDate") LocalDate toDate); }
注意:JPQL中使用的是实体名称(product是@Entity(name="product")指定的名称)和实体属性名(比如fromDate对应Orders类的fromDate属性),而非数据库表名和列名。
内容的提问来源于stack exchange,提问作者DanutSRL
相关产品推荐
相关产品推荐

