Spring Boot中Spring Data JPA原生查询选指定列时列缺失报错排查
解决Spring Data JPA原生查询部分列时的列缺失错误
这个问题我之前也碰到过,本质是Spring Data JPA在映射查询结果时的默认行为导致的——当你用原生查询只返回部分列,但仓库方法返回的是完整的Folder实体时,JPA会尝试给实体的所有字段赋值,一旦ResultSet里缺少某个实体字段对应的列(比如你报错的tpc_msc10_project_id,推测你的Folder实体实际包含这个字段但没在问题里列出),就会抛出这种列找不到的异常。下面给你几个实用的解决办法:
方案1:用DTO(数据传输对象)接收结果
这是最推荐的方式,清晰且符合单一职责原则:
- 先创建一个只包含你需要查询字段的DTO类,比如你只需要x和y列:
public class FolderPartialDTO { private int x; private int y; // 必须要有与查询列顺序匹配的构造函数 public FolderPartialDTO(int x, int y) { this.x = x; this.y = y; } // 按需添加getter方法 public int getX() { return x; } public int getY() { return y; } } - 然后在仓库接口里定义原生查询,指定返回类型为这个DTO:
@Repository public interface FolderRepository extends JpaRepository<Folder, Integer> { @Query(value = "SELECT f.x, f.y FROM folder f " + "JOIN folder parent ON f.parent_id = parent.id", // 替换成你的关联查询逻辑 nativeQuery = true) List<FolderPartialDTO> findSubfoldersWithParent(); }
Spring Data会自动通过构造函数把查询结果映射到DTO对象,不会再要求完整的实体字段。
方案2:返回Object[]或Map<String, Object>
如果不想额外创建DTO,可以直接返回原始的数组或Map:
- 返回
Object[]:
之后在业务层手动解析数组:@Query(value = "SELECT f.x, f.y FROM folder f JOIN ...", nativeQuery = true) List<Object[]> findSubfoldersWithParent();int x = (int) result[0]; int y = (int) result[1]; - 返回
Map<String, Object>(需要给查询列加别名):
这样可以通过键名获取值:@Query(value = "SELECT f.x AS folder_x, f.y AS folder_y FROM folder f JOIN ...", nativeQuery = true) List<Map<String, Object>> findSubfoldersWithParent();Integer x = (Integer) map.get("folder_x");
方案3:使用@SqlResultSetMapping进行自定义映射
如果你的查询逻辑比较复杂,或者需要复用映射规则,可以用这个方式:
- 先在
Folder实体上定义结果集映射:@Entity @SqlResultSetMapping( name = "FolderPartialMapping", classes = @ConstructorResult( targetClass = FolderPartialDTO.class, columns = { @ColumnResult(name = "x", type = Integer.class), @ColumnResult(name = "y", type = Integer.class) } ) ) public class Folder { // 你的实体字段,包括x、y、z以及报错的tpc_msc10_project_id等 private int x; private int y; private int z; private int tpcMsc10ProjectId; // 对应数据库列tpc_msc10_project_id // getter、setter、构造函数等 } - 然后在仓库方法里指定这个映射:
@Query(value = "SELECT f.x, f.y FROM folder f JOIN ...", nativeQuery = true, resultSetMapping = "FolderPartialMapping") List<FolderPartialDTO> findSubfoldersWithParent();
注意事项
- 检查你的原生SQL语句:确保查询的列名(或别名)和你要映射的DTO/实体字段对应;
- 如果你坚持要返回
Folder实体,那必须在查询中包含实体的所有字段,否则就会触发列缺失错误——这也是你当前报错的直接原因。
内容的提问来源于stack exchange,提问作者Prash
相关产品推荐
相关产品推荐

