DynamoDBPagingAndSortingRepository按createdAt排序报错如何解决
错误原因&修正方案
错误根因
你遇到的三个报错均由GSI注解配置错误和DynamoDB查询逻辑误用导致:
Sorting not supported for scan expressions:DynamoDB不支持全表Scan操作下的排序,排序必须基于GSI/主表的查询操作实现no HASH key for GSI:你创建的GSIid-createdAt-index的分区键为id,但你没有在实体类的id字段上标注对应的GSI分区键注解,反而给createdAt字段错误加了GSI分区键注解Both the Hash Key and the Range Key element in the KeySchema have the same name:你给createdAt字段同时配置了GSI的分区键和排序键,同一个字段不能在一个GSI里同时作为分区键和排序键
修正步骤
1. 调整GSI设计(前提)
你当前的GSI分区键设为唯一值id,每个分区仅存1条数据,排序完全无法生效。如果需要实现全表数据按createdAt全局倒序,需要调整GSI配置:
新增一个通用字段(比如bucket),所有数据的bucket字段统一存固定值1,将GSI的分区键设为bucket,排序键设为createdAt,所有数据会落在同一个GSI分区内,才能实现全局排序。
2. 修正实体类注解
按调整后的GSI配置修改注解:
@DynamoDBTable(tableName = "statements") class Statement { @get:DynamoDBAutoGeneratedKey @get:DynamoDBHashKey var id: String? = null // 新增GSI分区键字段 @get:DynamoDBAttribute @get:DynamoDBIndexHashKey(globalSecondaryIndexName = "bucket-createdAt-index") var bucket: Int = 1 @get:DynamoDBAttribute var statementText: String? = null @get:DynamoDBAttribute var source: String? = null @get:DynamoDBAttribute // 仅保留GSI排序键注解,删除之前加错的分区键注解 @get:DynamoDBIndexRangeKey(globalSecondaryIndexName = "bucket-createdAt-index") var createdAt: Long? = null }
3. 修正Repository查询方法
新增指定走GSI的查询方法,不能用默认的findAll(默认走全表Scan):
@Repository @EnableScan @EnableScanCount interface StatementRepository : DynamoDBPagingAndSortingRepository<Statement?, String?> { override fun findById(id: String): Optional<Statement?> // 新增按GSI分区键查询的方法,自动走对应的GSI,支持排序 fun findByBucket(bucket: Int, pageable: Pageable): Page<Statement> }
4. 修正Service调用逻辑
// 传入固定的bucket值1,触发GSI查询,支持按createdAt倒序 statementRepository.findByBucket(1, PageRequest.of(page, size, Sort.by("createdAt").descending())).forEach { // 业务逻辑处理 }
如果你的业务场景不需要全表全局排序,仅需要按某个业务字段(比如source)分组后组内按createdAt排序,把GSI的分区键换成source字段即可,逻辑和上面一致。
内容的提问来源于stack exchange,提问作者Prem
相关产品推荐
相关产品推荐

