AWS DynamoDB Java 替代注解的 SDK

AWS DynamoDB Java SDK alternative to annotations

我想避免在 class 上使用 DynamoDB 注释,但仍然能够使用映射器写入和读取 DynamoDB。我正在使用 Java SDK 从 DynamoDB 读取和写入(使用提供的 DynamoDBMapper

说我有这个Model.java

@DynamoDBTable(tableName="Model")
public class Model {

    private Integer id;
    private String title;

    @DynamoDBHashKey(attributeName="ModelId")  
    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    @DynamoDBAttribute(attributeName="Title")  
    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

我会照常给它写信

Model model = new Model();
//... random information

DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(model);

这很好,但是我的域对象上到处都是 DynamoDB 特定的注释。有没有办法用 class 包装域对象(没有任何注释)。在下面的例子中,我会寻找 DynamoDBModelWrapper

的有效实现
public class Model {
    private Integer id;
    private String title;

    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

public class DynamoDBModelWrapper extends Model { ... }

Model model = new Model();
//... random information

DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(DyanamoDBModelWrapper(model));

干杯,谢谢

这似乎是个糟糕的主意。您实际上必须强制所有 table 键和索引具有相同的名称。模型包装器不能只对每个模型属性应用相同的注解,它必须知道将哪个注解应用到哪个属性,这意味着仍然对模型应用注解 class,或者因为这是不允许的,强制模型 class 以特定方式命名属性。例如,您的主哈希键属性可能必须称为 primaryhashkey。

此外,您将无法使用 DyanmoDBMapper 的一些真正强大的部分,例如复杂和任意数据映射。

有一件事值得一提,你至少可以收拾一下。您的模型中有一些多余的文本 class。如果模型属性的名称与 table 属性不同,则只需指定 attributeName。如果它们匹配,您可以简单地忽略它。模型 class 名称和 table 名称也是如此。所以你可以这样做:

Table schema:
TableName: Model
Partition Key Attribute: id
Attribute: title

然后你的模型 class 看起来像这样

@DynamoDBTable
public class Model {

    private Integer id;
    private String title;

    @DynamoDBHashKey  
    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    @DynamoDBAttribute 
    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

注释还在,但看起来整洁多了。

这不是一个很好的解决方案 (IMO),所以希望有人提出更好的建议,但我做了以下事情:

public class Model {
    private Integer id;
    private String title;

    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

@DynamoDBTable(tableName="Model")
public class DynamoDBModelWrapper  {

    private final Model model;

    DynamoDBModelWrapper() {
        this.model = new Model();
    }
    DynamoDBModelWrapper(final Model model) {
        this.model = model;
    }

    @DynamoDBHashKey(attributeName="ModelId")  
    public Integer getId() { return model.id;}
    public void setId(Integer id) {model.id = id;}

    @DynamoDBAttribute(attributeName="Title")  
    public String getTitle() {return model.title; }
    public void setTitle(String title) { model.title = title; }
}

然后,您可以在从 DynamoDB 保存/加载时实例化 DynamoDBModelWrapper,并在其余时间使用不带任何 Dynamo 特定注释的对象。

Model model = new Model();
//... random information

DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(new DynamoDBModelWrapper(model));

在您的应用程序和 DynamoDB SDK 之间添加一个数据访问抽象层。您可以拥有单独的域和数据库模型 classes,并且数据访问层可以在它们之间进行转换。

这是它的工作原理。

定义一个 MyTableDataAccess 接口并实现 MyTableDataAccessDynamoDBImpl 或任何你想调用它的东西。您的应用程序代码将调用 MyTableDataAccess 的方法,这些方法应根据您的领域和业务用例进行定义。 MyTableDataAccessDynamoDBMpl 将负责域和数据库模型之间的转换,并进行实际的 dynamodb 调用。

目前,域模型和数据库模型可能具有完全相同的字段,因此它可能看起来多余,但这里有一些此策略的额外好处。

  • 您可以使您的域 class 不可变。 DynamoDBMapper 需要您要读取的所有字段的默认构造函数和设置器。通过拥有不同的域和数据库模型,您可以使数据库模型成为可变的 POJO,而您的域 class 可以是不可变的。
  • 如果您曾经切换过数据库,那么在一个地方创建数据访问层的新实现比替换整个应用程序中的所有 dynamodb 引用要容易得多。
  • 它允许您使用项目 TTL 或自动生成的字段等功能,而无需将它们暴露给您的应用程序。