用于不带注释的 DynamoDB 文档字段的 DynamoDBTypeConverter

Pau*_*ies 4 java amazon-dynamodb

我在 DynamoDB 中有一些条目,其中的字段如下,采用 DynamoDB 文档格式:

{ "foo" : { "N" : "45" }, "bar" : { "N" : "12" }}

我有一个代表文档类型的 Java 类:

public class FooBar {
  private final int foo;
  private final int bar;

  public FooBar(
      int foo,
      int bar
  ) {
    this.foo = foo;
    this.bar = bar;
  }

  public int getFoo() {
    return foo;
  }

  public int getBar() {
    return bar;
  }
}
Run Code Online (Sandbox Code Playgroud)

我想使用DynamoDB 映射器来获取行并将其放入表中(为简洁起见,省略了表示整行的中间类)。我不想将 DynamoDB 注释(等)添加@DynamoDBDocument@DynamoDBAttribute类中FooBar,因为它们需要零参数构造函数和 setter 方法,但这应该是不可变的数据对象。

因此,我想使用 DynamoDBTypeConverter 如此处所述来编写我自己的转换,但我找不到合适的“源”类型(用于替换[?]):

class FooBarConverter implements DynamoDBTypeConverter<[?], FooBar> {
  @Override
  public [?] convert(FooBar object) {
    ...
  }

  @Override
  public FooBar unconvert([?] object) {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)
  • 地图,这似乎是最自然的,失败了DynamoDBMappingException: not supported; requires @DynamoDBTyped or @DynamoDBTypeConverted
  • 字符串,这似乎是一个合理的默认值,不会出错,但提供给该convert()方法的字符串始终为空
  • 对象,这似乎是一个包罗万象的对象,不受 Dynamo 支持,并且失败并显示DynamoDBMappingException: could not resolve type of class FooBarConverter

如果我们把Java类和存储格式都视为不可修改,有什么解决办法呢?

Pau*_*ies 5

我找到了一个合适的类型用于源 - AttributeValue. 这是转换器:

public class FooBarConverter implements DynamoDBTypeConverter<AttributeValue, FooBar> {
  @Override
  public AttributeValue convert(FooBar object) {
    return new AttributeValue()
        .addMEntry("foo", new AttributeValue().withN(Integer.toString(object.getFoo())))
        .addMEntry("bar", new AttributeValue().withN(Integer.toString(object.getBar())));
  }

  @Override
  public FooBar unconvert(AttributeValue object) {
    Map<String, AttributeValue> objectM = object.getM();
    int foo = Integer.parseInt(objectM.get("foo").getN());
    int bar = Integer.parseInt(objectM.get("bar").getN());
    return new FooBar(foo, bar);
  }
}
Run Code Online (Sandbox Code Playgroud)

另外,还有一个代表 Dynamo 中整行的类:

public class FooBarRow {
  private String key;
  private FooBar fooBar;

  public FooBarRow(
      String key,
      FooBar fooBar
  ) {
    this.key = key;
    this.fooBar = fooBar;
  }

  public FooBarRow() {
  }

  @DynamoDBHashKey
  public String getKey() {
    return key;
  }

  public void setKey(String key) {
    this.key = key;
  }

  @DynamoDBTypeConverted(converter = FooBarConverter.class)
  public FooBar getFooBar() {
    return fooBar;
  }

  public void setFooBar(FooBar fooBar) {
    this.fooBar = fooBar;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,FooBarRow使用 a 保存和加载实例DynamoDBMapper可以完美地工作。

public class FooBarMain {
  public static void main(String[] args) {
    DynamoDBMapper mapper = new DynamoDBMapper(
        AmazonDynamoDBClientBuilder.standard().build(),
        DynamoDBMapperConfig
            .builder()
            .withTableNameOverride(new DynamoDBMapperConfig.TableNameOverride("foobar"))
            .build()
    );

    mapper.save(new FooBarRow("foobar1", new FooBar(123, 4)));

    mapper.load(FooBarRow.class, "foobar1").getFooBar();
  }
}
Run Code Online (Sandbox Code Playgroud)