AWS DynamoDB Java SDK替代注释

时间:2018-01-10 18:50:41

标签: java amazon-web-services amazon-dynamodb aws-java-sdk

我想避免在类上使用DynamoDB Annotations,但仍然可以使用映射器来编写和读取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特定的注释。有没有办法让一个包裹域对象的类(没有任何注释)。在下面的例子中,我将寻找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));

干杯谢谢

3 个答案:

答案 0 :(得分:0)

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

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

有一点要提到的是,你至少可以整理一下。您的模型类中有一些多余的文本。如果模型属性的名称与表属性不同,则只需指定attributeName。如果它们匹配,您可以简单地省略它。模型类名称和tableName也是如此。所以你可以这样做:

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

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

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

注释仍然存在,但它看起来更整洁。

答案 1 :(得分:0)

这不是一个很好的解决方案(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保存/加载并使用没有任何Dynamo特定注释的对象时,可以实例化DynamoDBModelWrapper。

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

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

答案 2 :(得分:0)

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

这是它的工作方式。

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

现在,域和数据库模型可能具有完全相同的字段,因此看起来似乎是多余的,但这是该策略的一些其他优点。

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