【问题标题】:DynamoDBMapper support for inheritanceDynamoDBMapper 支持继承
【发布时间】:2016-08-30 07:38:21
【问题描述】:

我正在使用 dynamodb,我存储的 java 类具有以下结构:

@DynamoDBTable(tableName="Animals")
class abstract Animal {

  @DynamoDBHashKey(attributeName = "Id")
  @DynamoDBAutoGeneratedKey
  String id;

}

class Dog extends Animal {
  // ... dog props
}

class Cat extends Animal {
  // ... cat props
}

我想将 Dog/Cat 的实例保存到数据库并检索它们。准备提供类似于@JsonTypeInfo 之类的元信息。

如果支持,请告诉我。或者在 DynamoDb 中存储来自 Java 的多态类型的任何解决方法。

提前致谢,

【问题讨论】:

    标签: amazon-web-services amazon-dynamodb


    【解决方案1】:

    您可以使用如上所述的继承概念。 DynamoDBMapper save() 方法应该能够成功保存 Dog 和 Cat。

    但是,当您使用 DynamoDBMapper load() 检索数据时,您需要提供正确的类名。

    使用 Animal.class 执行 load() 方法时,如果 Animal 类定义为抽象类,API 将抛出“Failed to instantiate class”异常。

    获取动物数据的示例 load() 方法:-

    dynamoDBMapper.load(Animal.class,id,
                        new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT));
    

    例外:-

    Caused by: com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: Failed to instantiate class
    

    解决方法 1:-

    您可以使用 QuerySpec 获取 Animal 数据。这样做的缺点是您需要单独获取每个键的值,因为您没有使用 DynamoDBMapper 类获取数据。

    DynamoDB dynamoDB = new DynamoDB(dynamoDBClient);
    
            Table table = dynamoDB.getTable("Animals");
    
            ItemCollection<QueryOutcome> items = null;
    
            QuerySpec querySpec = new QuerySpec();
    
            querySpec.withKeyConditionExpression("Id = :val1").withValueMap(new ValueMap().withString(":val1", animalId));
            items = table.query(querySpec);
    
            Iterator<Item> iterator = items.iterator();
    
            while (iterator.hasNext()) {
                Item itemData = iterator.next();
    
                System.out.println("Json data ====================>" + itemData.toJSONPretty());
                System.out.println("Dogname : " + itemData.getString("dogname"));
                System.out.println("Catname : " + itemData.getString("catname"));
    
            }
    

    解决方法 2:-

    您可以将 Animal 类声明为普通类(即没有抽象)。在这种方法中,您可以使用 DynamoDBMapper 获取数据。但是,您不会看到子类属性。

    如果您知道要获取 CAT 或 DOG 对象,则可以在 load() 期间将其指定为相应的类名。

    当你得到狗时:-

    Dog dog = dynamoDBMapper.load(Dog.class, id,
                        new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT));
    

    获得 CAT 后:-

    Cat cat = dynamoDBMapper.load(Cat.class, id,
                        new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT));
    

    【讨论】:

    • 这意味着,保存时我可以保存 Dog/Cat 并将其保存到数据库中(可能与 Animal 类中的附加字段 'type' == 'Dog'/'Cat' )。在检索时,我应该使用 QuerySpec 读取,并读取为 JSON,并根据类型,将适当的 clazz 传递给 jackson 并反序列化它。那是对的吗?但我希望 SDK 默认支持这一点,就像 hibernate 一样,因为文档数据库自然是多态的。
    • **(可能与 Animal 类中的附加字段 'type' == 'Dog'/'Cat' 一起) - 我的意思是手动添加类型信息。
    • 是的,你的理解是正确的。您可以将数据与附加字段一起成功保存。此外,Dynamodb 是一个键/值数据库。
    • 这个答案有帮助吗?
    • 终于使用了低级api(“Item” api)并使用Jackson在dynamo外部进行了序列化/反序列化。
    【解决方案2】:

    您可以使用@DynamoDBDocument 来序列化对象。该文档也有一个很好的示例来演示此注释的用法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2012-01-25
      • 2011-04-21
      • 1970-01-01
      相关资源
      最近更新 更多