问题
I am trying to create a dynamoDBMapper annotation for the below case.
I have EmployeeLevelTrail which is a class of a Employee level record
@DynamoDBTable(tableName = TABLE_NAME)
public class EmployeeData {
public final static String TABLE_NAME = “EmployeeDataRecord”;
@DynamoDBAttribute(attributeName = “employeeID”)
public String EmployeeID;
@DynamoDBAttribute(attributeName = “EmployeeLevelDataRecords”)
@DynamoDBTyped(DynamoDBMapperFieldModel.DynamoDBAttributeType.M)
public EmployeeLevelTrail employeeLevelTrail
}
public class EmployeeLevelTrail {
public final static String DDB_ATTR_EMPLOYEE_LEVEL_TRAIL = “employeeLevelTrail”;
@DynamoDBAttribute(attributeName = DDB_ATTR_EMPLOYEE_LEVEL_TRAIL)
private List<EmployeeLevelRecord> thisEmployeeLevelRecords;
public void appendEmployeeLevelRecord(@NonNull EmployeeLevelRecord employeeLevelRecord) {
thisEmployeeLevelRecords.add(employeeLevelRecord);
}
}
public class EmployeeLevelRecord {
private String Level;
private String Manager;
private Instant timeOfEvent;
}
This is my annotation but it is not correct as I am not able to save my DynamoDB data
回答1:
To mark another class as part of the data model for DynamoDBMapper, you can annotate it with @DynamoDBDocument, which tells DynamoDBMapper that a class can be serialized as a DynamoDB document.
For classes that you aren't writing (ie. from the Java library or an external library) or if you need more control over how to serialize one of your own classes, you can use @DynamoDBTypeConverted
, which allows you to map arbitrary data by providing your own DynamoDBTypeConverter implementation to convert from any Java object to any supported DynamoDB type.
Using your sample code, I've added in the appropriate @DynamoDBDocument
and @DynamoDBTypeConverted
annotations, as well as a sample implementation of a DynamoDBTypeConverter
that converts an Instant
to a ISO-8601 String
. If employeeId
is the hash key of your table, make sure you also add the @DynamoDBHashKey
annotation to employeeId
.
@DynamoDBTable(tableName = TABLE_NAME)
public class EmployeeData {
public final static String TABLE_NAME = “EmployeeDataRecord”;
@DynamoDBAttribute(attributeName = “employeeID”)
public String EmployeeID;
@DynamoDBAttribute(attributeName = “EmployeeLevelDataRecords”)
public EmployeeLevelTrail employeeLevelTrail
}
@DynamoDBDocument
public class EmployeeLevelTrail {
public final static String DDB_ATTR_EMPLOYEE_LEVEL_TRAIL = “employeeLevelTrail”;
@DynamoDBAttribute(attributeName = DDB_ATTR_EMPLOYEE_LEVEL_TRAIL)
private List<EmployeeLevelRecord> thisEmployeeLevelRecords;
public void appendEmployeeLevelRecord(@NonNull EmployeeLevelRecord employeeLevelRecord) {
thisEmployeeLevelRecords.add(employeeLevelRecord);
}
}
@DynamoDBDocument
public class EmployeeLevelRecord {
private String Level;
private String Manager;
@DynamoDBTypeConverted(converter = InstantToStringTypeConverter.class)
private Instant timeOfEvent;
}
public class InstantToStringTypeConverter implements DynamoDBTypeConverter<String, Instant> {
@Override
public String convert(final Instant instant) {
return instant.toString();
}
@Override
public Instant unconvert(final String string) {
return Instant.parse(string);
}
}
回答2:
I reached to the solution using the below code. With only @DynamoDBTypeConvertedJSON, I was able to create an entry in the table but not update it as I was running into mapping Dynamo DB mapping exception.
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@DynamoDBTable(tableName = TABLE_NAME)
public class EmployeeData {
public final static String TABLE_NAME = "EmployeeData";
public final static String DDB_ATTR_ID = "Id";
public final static String DDB_ATTR_EMPLOYEE_LEVEL_RECORD_TRAIL = "EmployeeLevelRecordTrail";
@DynamoDBHashKey(attributeName = DDB_ATTR_ID)
@DynamoDBAttribute(attributeName = DDB_ATTR_ID)
private String id;
@DynamoDBAttribute(attributeName = DDB_ATTR_EMPLOYEE_LEVEL_RECORD_TRAIL)
@DynamoDBTypeConverted(converter = EmployeeLevelRecordTrailConverter.class)
private EmployeeLevelRecordTrail employeeLevelRecordTrail;
@DynamoDBAttribute(attributeName = DDB_ATTR_CREATED_TIME)
@DynamoDBTypeConverted(converter = InstantConverter.class)
private Instant joiningTime;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeLevelRecordTrail {
private List<EmployeeLevelRecord> thisEmployeeLevelRecords;
public void appendEmployeeLevelRecord(@NonNull EmployeeLevelRecord employeeLevelRecord) {
thisEmployeeLevelRecords.add(employeeLevelRecord);
}
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@DynamoDBDocument
public class EmployeeLevelRecord {
private String Level;
private String Manager;
@DynamoDBTypeConverted(converter = InstantConverter.class)
private Instant timeOfEvent;
}
public class EmployeeLevelRecordTrailConverter implements
DynamoDBTypeConverter<List<EmployeeLevelRecord>, EmployeeLevelRecordTrail> {
@Override
public List<EmployeeLevelRecord> convert(EmployeeLevelRecordTrail employeeLevelRecordTrail) {
return employeeLevelRecordTrail.getEmployeeLevelRecord();
}
@Override
public EmployeeLevelRecordTrail unconvert(List<EmployeeLevelRecord> thisEmployeeLevelRecords) {
return new EmployeeLevelRecordTrail(thisEmployeeLevelRecords);
}
}
public class InstantConverter implements DynamoDBTypeConverter<String, Instant> {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_INSTANT;
@Override
public String convert(Instant instant) {
return instant == null ? null : DATE_TIME_FORMATTER.format(instant);
}
@Override
public Instant unconvert(String str) {
return str == null ? null : Instant.from(DATE_TIME_FORMATTER.parse(str));
}
}
Reading the documentation on how to do mapping helped.
回答3:
You need to use the DynamoDBTypeConverted
annotation. You will also need to create a converter class which defines how to get from your Java object to a DynamoDB primitive (probably a string).
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.ArbitraryDataMapping.html
You can also check out an example from this answer:
DynamoDB JsonMarshaller cannot Deserialize List of Object
来源:https://stackoverflow.com/questions/54992305/dynamodb-mapper-annotation-for-object-which-has-list-of-another-object