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

Spring Boot JPA对接Redshift时分页查询语法错误问题

问题场景

我开发Spring Boot GraphQL服务,用JPA连接Redshift,常规查询正常,但分页时Redshift返回语法错误。

控制器代码:

@QueryMapping("allProductsPaginationed")
List<Product> getProductsPaginated(@Argument("pageNumber") int pageNumber, @Argument("limit") int limit) {
    return this.productService.getProductsPaginated(pageNumber, limit);
}

服务层代码:

public List<Product> getProductsPaginated(int pageNumber, int limit) {
    Pageable pageable = PageRequest.of(pageNumber, limit);
    Page<Product> productPage = productRepo.findAll(pageable);
    return productPage.getContent();
}

仓库代码:

@Repository 
public interface ProductRepo extends JpaRepository<Product, String> {
}

JPA生成的SQL:

select
    p1_0.product_id,
    p1_0.product_name,
    ....
from
    productmart.product p1_0 offset ? rows fetch first ? rows only

Redshift报错信息:

Caused by: com.amazon.support.exceptions.ErrorException: [Amazon](500310) Invalid operation: syntax error at or near "rows" 
Position: 1267;
问题分析

Redshift不支持SQL标准的OFFSET ... ROWS FETCH FIRST ... ROWS ONLY分页语法,它采用PostgreSQL风格的LIMIT <条数> OFFSET <偏移量>语法,这是导致报错的核心原因。

解决方案

方法一:配置Redshift专用Hibernate方言(推荐)

Spring JPA生成的SQL语法由Hibernate方言控制,配置Redshift对应的方言后,JPA会自动生成兼容的分页SQL:

  1. 在application.properties中添加方言配置:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.RedshiftDialect

(注:Hibernate 6.x版本需使用org.hibernate.dialect.PostgreSQLRedshiftDialect,请根据依赖版本调整)

  1. 无需修改现有业务代码,重启服务后,JPA生成的SQL会变为:
select p1_0.product_id, p1_0.product_name, ... from productmart.product p1_0 limit ? offset ?

该语法可被Redshift正常解析。

方法二:自定义原生SQL查询

如果不想依赖方言配置,可在Repository中手动编写Redshift兼容的原生查询:

  1. 修改ProductRepo,添加自定义分页方法:
@Repository 
public interface ProductRepo extends JpaRepository<Product, String> {
    @Query(value = "SELECT * FROM productmart.product LIMIT :limit OFFSET :offset", nativeQuery = true)
    List<Product> findProductsPaginated(@Param("limit") int limit, @Param("offset") int offset);
}
  1. 调整Service层代码,计算偏移量(偏移量 = 页码 × 每页条数):
public List<Product> getProductsPaginated(int pageNumber, int limit) {
    int offset = pageNumber * limit;
    return productRepo.findProductsPaginated(limit, offset);
}
验证

完成配置或代码修改后,重新发起分页查询,Redshift即可正常返回分页结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:45:24