SpringBoot编写DynamoDB自定义查询报错问题排查
问题场景
基于cost字段查询DynamoDB表ProductInfo时,通过CLI执行以下命令可以正常返回正确结果:
aws dynamodb execute-statement --statement "SELECT * FROM ProductInfo WHERE cost='1000'" --endpoint-url http://localhost:8000
但在Spring Boot项目中实现相同查询逻辑时,抛出如下错误:
AmazonDynamoDBException: Can not use both expression and non-expression parameters in the same request
项目配置参照Spring Data DynamoDB配置教程编写,Repository层初始代码如下:
import org.socialsignin.spring.data.dynamodb.repository.EnableScan; import org.socialsignin.spring.data.dynamodb.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; @EnableScan public interface ProductInfoRepository extends CrudRepository<ProductInfo, String> { @Query(fields = "select * from ProductInfo where cost = :cost") List<ProductInfo> findAllProductByCost(@Param("cost") String cost); }
错误原因
报错核心原因是@Query注解属性使用错误:spring-data-dynamodb提供的@Query注解中,fields属性仅用于声明查询需要返回的字段列表,不支持传入完整的查询语句。当把完整查询语句写在fields属性中时,框架底层会自动生成一套基于DynamoDB表达式API的查询参数,同时又会将fields中写入的语句解析为非表达式类请求参数,两类参数同时提交给DynamoDB客户端就会触发该报错。
修复方案
两种实现方式二选一即可:
- 方案1:使用Spring Data派生查询,无需手写
@Query
因为Repository类上已经加了@EnableScan注解,支持全表扫描匹配非主键字段,直接按照Spring Data方法命名规则写查询方法即可,框架会自动生成正确的查询逻辑:import org.socialsignin.spring.data.dynamodb.repository.EnableScan; import org.springframework.data.repository.CrudRepository; import java.util.List; @EnableScan public interface ProductInfoRepository extends CrudRepository<ProductInfo, String> { // 框架自动派生查询逻辑,匹配cost字段等于入参的记录 List<ProductInfo> findAllByCost(String cost); } - 方案2:正确使用
@Query注解
如果需要显式使用@Query,仅把需要返回的字段传入fields属性即可,查询条件通过方法名派生,不需要写完整查询语句:import org.socialsignin.spring.data.dynamodb.repository.EnableScan; import org.socialsignin.spring.data.dynamodb.repository.Query; import org.springframework.data.repository.CrudRepository; import java.util.List; @EnableScan public interface ProductInfoRepository extends CrudRepository<ProductInfo, String> { // fields仅指定返回字段,查询条件由方法名自动派生 @Query(fields = "*") List<ProductInfo> findAllByCost(String cost); }
注意:如果
cost不是ProductInfo表的分区键或排序键,必须保留Repository类上的@EnableScan注解,否则会抛出查询必须指定主键条件的错误。
内容的提问来源于stack exchange,提问作者Sumanth H S
相关产品推荐
相关产品推荐

