Spring Data JPA @Query原生查询报错,MySQL单独执行正常
核心原因
查询结果与实体类不匹配
你的SQL子查询仅返回fromName、toName、departure、arrival四个字段,但方法返回的是Page<Flight>,而Flight实体必然包含更多属性(如主键、航班号等)。Hibernate无法将仅四个字段的查询结果映射到完整的Flight实体,进而触发底层SQL语法解析异常(表面表现为语法错误)。Spring Data JPA分页拼接SQL冲突
当使用nativeQuery=true结合Pageable时,Spring Data JPA会自动生成分页语句和count查询。对于嵌套子查询的原生SQL,部分版本的框架在拼接这些附加语句时会破坏原SQL结构,导致出现多余括号或语法混乱,比如报错信息中出现的inner)语法错误。参数绑定顺序不明确
你的方法参数顺序为Pageable、departure、arrival、fromName、toName,但@Query中的参数引用顺序是:fromName、:toName、:departure、:arrival,且未使用@Param注解明确绑定参数。虽然这一般不会直接引发语法错误,但可能导致参数值错误绑定,间接引发异常。
解决方案
方案1:修改SQL返回完整Flight实体字段
去掉嵌套子查询,直接关联查询并返回flight表的所有字段,同时查询机场名称(需在Flight实体中添加fromName、toName属性,可标注@Transient避免数据库映射):
@Repository public interface FlightRepository extends PagingAndSortingRepository<Flight, Integer> { @Query(nativeQuery = true, value = "select flight.*, a.name as fromName, a2.name as toName " + "from flight " + "inner join airport a on `from` = a.airport_id " + "inner join airport a2 on `to` = a2.airport_id " + "where a.name = :fromName " + "and a2.name = :toName " + "and date(flight.departure) = :departure " + "and date(flight.arrival) = :arrival") Page<Flight> querySearchResult(Pageable pageable, @Param("departure") LocalDate departure, @Param("arrival") LocalDate arrival, @Param("fromName") String fromName, @Param("toName") String toName); }
方案2:使用DTO接收查询结果
创建专门的DTO类来接收查询结果,避免与Flight实体的字段不匹配问题:
// 定义DTO类 public class FlightSearchResultDTO { private String fromName; private String toName; private LocalDateTime departure; private LocalDateTime arrival; // 构造方法、getter/setter public FlightSearchResultDTO(String fromName, String toName, LocalDateTime departure, LocalDateTime arrival) { this.fromName = fromName; this.toName = toName; this.departure = departure; this.arrival = arrival; } // getter方法 public String getFromName() { return fromName; } public String getToName() { return toName; } public LocalDateTime getDeparture() { return departure; } public LocalDateTime getArrival() { return arrival; } } // 修改Repository方法 @Repository public interface FlightRepository extends PagingAndSortingRepository<Flight, Integer> { @Query(nativeQuery = true, value = "select a.name as fromName,a2.name as toName,departure,arrival " + "from flight " + "inner join airport a on `from` = a.airport_id " + "inner join airport a2 on `to` = a2.airport_id " + "where a.name = :fromName " + "and a2.name = :toName " + "and date(departure) = :departure " + "and date(arrival) = :arrival") Page<FlightSearchResultDTO> querySearchResult(Pageable pageable, @Param("departure") LocalDate departure, @Param("arrival") LocalDate arrival, @Param("fromName") String fromName, @Param("toName") String toName); }
方案3:明确参数绑定
无论使用哪种方案,都建议给方法参数添加@Param注解,确保参数与@Query中的引用一一对应,避免顺序问题引发的错误。
内容的提问来源于stack exchange,提问作者AMZ

