Java SDK v2扫描DynamoDB列表嵌套Map属性映射异常解决方案问询
解决方案
你遇到的异常是因为DynamoDB Enhanced Client没有默认注册List<Map<String,String>>类型的转换器,可通过以下两种方式解决:
方案1:使用自定义转换器(推荐,适配性最强)
第一步:实现自定义属性转换器
实现AttributeConverter接口,完成Java对象和DynamoDB AttributeValue的双向转换:
import software.amazon.awssdk.enhanced.dynamodb.AttributeConverter; import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; import software.amazon.awssdk.enhanced.dynamodb.EnhancedType; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class AccountListConverter implements AttributeConverter<List<Map<String, String>>> { @Override public AttributeValue transformTo(List<Map<String, String>> input) { // 将Java List<Map>转为DynamoDB的L类型(列表类型) List<AttributeValue> listValues = input.stream() .map(map -> AttributeValue.builder().m( map.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> AttributeValue.builder().s(entry.getValue()).build() )) ).build()) .collect(Collectors.toList()); return AttributeValue.builder().l(listValues).build(); } @Override public List<Map<String, String>> transformFrom(AttributeValue input) { // 将DynamoDB的L类型转回Java List<Map> return input.l().stream() .map(item -> item.m().entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().s() )) ) .collect(Collectors.toList()); } @Override public EnhancedType<List<Map<String, String>>> type() { return EnhancedType.listOf(EnhancedType.mapOf(String.class, String.class)); } @Override public AttributeValueType attributeValueType() { return AttributeValueType.L; } }
第二步:在StaticTableSchema中关联转换器
修正你现有代码的属性定义,补充getter和转换器配置即可:
final StaticTableSchema<Target> tableSchema = StaticTableSchema.builder(Target.class) .newItemSupplier(Target::new) .addAttribute(String.class, a -> a.name("Name") .getter(Target::getName) .setter(Target::setName) .tags(DynamoDbPartitionKeyTag.create()) // 标记分区键 ) .addAttribute(EnhancedType.listOf(EnhancedType.mapOf(String.class, String.class)), a -> a.name("Accounts") .getter(Target::getAccounts) // 补充缺失的getter配置 .setter(Target::setAccounts) .attributeConverter(new AccountListConverter()) // 绑定自定义转换器 ) .build();
方案2:使用注解简化配置(适合优先用注解的场景)
如果你不用手动写StaticTableSchema,直接在DynamoDbBean的字段上加转换器注解即可:
@DynamoDbBean public class Target { private String name; private List<Map<String,String>> accounts; @DynamoDbPartitionKey public String getName() { return name; } public void setName(String name) { this.name = name; } @DynamoDbConvertedBy(AccountListConverter.class) public List<Map<String, String>> getAccounts() { return accounts; } public void setAccounts(List<Map<String, String>> accounts) { this.accounts = accounts; } }
直接用DynamoDbEnhancedClient.table("你的表名", TableSchema.fromBean(Target.class))就能完成映射,不需要手动写StaticTableSchema。
注意事项
- 你现有代码中类名不一致(一会儿是Target一会儿是TargetCompany),请统一类名避免编译错误
- 如果你的Map里的值不只有String类型,可在转换器的transformTo和transformFrom方法中扩展对应类型的转换逻辑即可
内容的提问来源于stack exchange,提问作者levye
相关产品推荐
相关产品推荐

