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

Spring Data JPA原生查询报SQLGrammarException:按ID查指定列失败

Spring Data JPA原生查询报错:Column 'id' not found 排查方案

问题场景

刚接触Spring Data JPA,在Spring Boot项目中编写原生Query,希望根据ID获取对应first_name(数据库列名为first_name)的数据。该SQL语句在MySQL数据库中能正常执行,但代码运行时抛出org.springframework.dao.InvalidDataAccessResourceUsageException,嵌套异常为org.hibernate.exception.SQLGrammarException,提示'Column 'id' not found'。

相关代码

实体类(EmployeeEntity)

package com.jpademo.demo.entity;

import lombok.*;

import javax.persistence.*;

@Data
@NoArgsConstructor
@Setter
@Getter
@ToString
@Entity
@Table(name = "TBL_EMPLOYEES")
public class EmployeeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email", nullable = false, length = 200)
    private String email;

    public EmployeeEntity(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

}

仓库接口(EmployeeRepository)

package com.jpademo.demo.repository;

import com.jpademo.demo.entity.EmployeeEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface EmployeeRepository extends JpaRepository <EmployeeEntity, Long>{
    // 派生查询
    Optional<EmployeeEntity> findByFirstName(String firstName);

    // 原生查询
    @Query(nativeQuery=true, value="select * from TBL_EMPLOYEES where id=:id" )
    Optional<EmployeeEntity> findDataById(@Param("id") long id);

    @Query(nativeQuery=true, value="select first_name from TBL_EMPLOYEES where id=:id" )
    Optional<EmployeeEntity> findFirstNameById(@Param("id") long id);

    @Query(nativeQuery=true, value="select email from TBL_EMPLOYEES where id=:id" )
    Optional<EmployeeEntity> findEmailById(@Param("id") long id);
}

调用测试方法

@Test
void nativeQuery2(){
    System.out.println("******* TEST ********");
    Optional<EmployeeEntity> response = employeeRepository.findFirstNameById(1L);

    if(response.isEmpty()) {
        System.out.println("********* No Record Found with this Id *********");
    }else{
        System.out.println(response.toString());
    }
}

堆栈信息

******* TEST ********
Hibernate: 
    select
        first_name 
    from
        TBL_EMPLOYEES 
    where
        id=?
2023-10-04 11:54:54.964  WARN 1732 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: S0022
2023-10-04 11:54:54.964 ERROR 1732 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column 'id' not found.

org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select first_name from TBL_EMPLOYEES where id=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query

表结构说明

数据库表TBL_EMPLOYEES包含主键列(疑似名为EMPLOYEE_ID)、first_name、last_name、email等列。

原因分析与解决方法

核心原因1:查询结果无法映射到实体类

findFirstNameById方法返回类型是Optional<EmployeeEntity>,但原生查询只返回了first_name单个字段。Hibernate映射实体类时,必须找到@Id标注的id字段对应列值,而查询结果中没有id列,因此抛出Column 'id' not found错误。

解决方法:
如果仅需获取first_name,直接修改方法返回类型为Optional<String>,无需映射到完整实体:

@Query(nativeQuery=true, value="select first_name from TBL_EMPLOYEES where id=:id" )
Optional<String> findFirstNameById(@Param("id") long id);

调用时直接处理字符串结果:

@Test
void nativeQuery2(){
    System.out.println("******* TEST ********");
    Optional<String> response = employeeRepository.findFirstNameById(1L);

    if(response.isEmpty()) {
        System.out.println("********* No Record Found with this Id *********");
    }else{
        System.out.println("First Name: " + response.get());
    }
}

核心原因2:实体类字段与数据库列名不匹配

从表结构推测,数据库主键列可能不是id,而是EMPLOYEE_ID(或其他名称)。实体类id字段未指定@Column注解,JPA默认使用字段名id作为数据库列名,导致SQL中where id=:id找不到对应列。

解决方法:

  1. 修改实体类id字段,添加@Column注解指定数据库实际列名:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "EMPLOYEE_ID") // 替换为数据库实际主键列名
private long id;
  1. 同步修改原生查询的where条件,使用数据库实际列名:
@Query(nativeQuery=true, value="select first_name from TBL_EMPLOYEES where EMPLOYEE_ID=:id" )
Optional<String> findFirstNameById(@Param("id") long id);

额外建议

  • 编写原生查询时,确保SQL列名与数据库实际列名完全一致;
  • 若只需获取单个或部分字段,优先使用对应数据类型作为返回值,避免强制映射到完整实体类;
  • 开启spring.jpa.show-sql=true配置,查看Hibernate生成的SQL,方便排查字段匹配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 09:02:07