使用Java Generics时的DynamoDBMappingException

时间:2016-03-29 20:49:47

标签: java generics amazon-dynamodb

我有一个名为' inbox'的DynamoDB表。在其中将存储发送给用户和从用户发送的消息。将有多种类型的消息,并且基于类型,数据可能随消息一起出现。我有一个映射到收件箱表的对象UserMessage。虽然所有消息都有公共字段(例如sendTo,sentFrom),但数据结构会有所不同。

使用Java Generics可能是一种更好的方法,而不是使用Map来表示这些数据。我有一个使用@DynamoDBDocument注释的对象,DynamoDBMapper会将其序列化为JSON。当成员变量声明为:

@DynamoDBTable(tableName="inbox")
public class UserMessage<T> {

    private String toId;
    private T data;

@DynamoDBAttribute(attributeName="data")
public T getData() {
    return data;
}
public void setData(T data) {
    this.data = data;
}
@DynamoDBHashKey(attributeName="toId")
public String getToId() {
     return toId;
}
public void setToId(String to) {
    this.toId = to;
   }
}
确实,结果是预料之中的。数据被序列化为JSON并以ContactData的注释格式存储在收件箱的data属性中。但是,为了通过使用泛型类型获得所需的灵活性,对DynamoDBMapper.save()的调用会抛出DynamoDBMappingException:无法将T转换为类。

这是UserMessage类:

@DynamoDBDocument
public class ContactData {

    private String firstname;
    private String lastname;
    private String email;

 @DynamoDBAttribute(attributeName = "firstname")
public String getFirstname() {
    return firstname;
}
public void setFirstname(String firstname) {
    this.firstname = firstname;
}
 @DynamoDBAttribute(attributeName = "lastname")
public String getLastname() {
    return lastname;
}
public void setLastname(String lastname) {
    this.lastname = lastname;
}
 @DynamoDBAttribute(attributeName = "email")
public String getEmail() {
    return email;
}
public void setEmail(String email) {
    this.email = email;
}
}

ContactData的代码:

UserMessage<ContactData> message = new UserMessage<ContactData>();
ContactData cd = new ContactData();
cd.setEmail("jane@test.com");
cd.setFirstname("Jane");
cd.setLastname("Smith");

message.setToId("test@email.com");
message.setData(cd)
DynamoDB.getMapper().save(message);

设置它的控制器代码是:

{{1}}

我相当缺乏经验,而且通用类型对我来说是全新的,所以我希望我正确使用它们。我觉得我是。我只是认为DynamoDBMapper在这种情况下无法映射到正确的类。 谢谢 杰夫

1 个答案:

答案 0 :(得分:0)

每次使用非标准属性类时,都需要提供编组器。在这里,我使用了一个全局的Object marshaller,您可以使用 JSON-ify 任何您想要的东西。

我个人更喜欢使用静态类型,每个类型都有一个我可以推理的定义的编组器,但是ymmv。

public class GenericDBEntity<T>
{
    ..
    private T extra;

    @DynamoDBAttribute
    @DynamoDBMarshalling(marshallerClass=ObjectMarshaller.class)
    public T getExtra()
    {
        return extra;
    }
    public void setExtra(T extra)
    {
        this.extra = extra;
    }

    public static class ObjectMarshaller implements DynamoDBMarshaller<Object>
    {
        @Override
        public String marshall(Object getterReturnResult)
        {
            return getterReturnResult.toString();
        }

        @Override
        public Object unmarshall(Class<Object> clazz, String obj)
        {
            return obj;
        }
    }
}