DynamoDBTypeConverter for DynamoDB document field without annotations

DynamoDBTypeConverter for DynamoDB document field without annotations

我在 DynamoDB 中有一些条目,其中有一个字段,在 DynamoDB 文档格式中:

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

我有一个 Java class 表示文档类型:

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;
  }
}

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

所以想用DynamoDBTypeConverter (as described here)自己写转换,但是找不到suitable'source'类型(来代替[?]):

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

  @Override
  public FooBar unconvert([?] object) {
    ...
  }
}

如果把Javaclass和存储格式都看成是不可修改的,有什么办法呢?

我找到了适合源的类型 - 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);
  }
}

此外,class 表示 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;
  }
}

现在,使用 DynamoDBMapper 保存和加载 FooBarRow 个实例效果很好。

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();
  }
}