J'essaye de créer une annotation dynamoDBMapper pour le cas ci-dessous.
J'ai EmployeeLevelTrail qui est une classe d'un enregistrement de niveau Employee
@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; }
Ceci est mon annotation mais ce n'est pas correct car je ne parviens pas à enregistrer mes données DynamoDB
3 Réponses :
Vous devez utiliser l'annotation DynamoDBTypeConverted
. Vous devrez également créer une classe de convertisseur qui définit comment passer de votre objet Java à une primitive DynamoDB (probablement une chaîne).
Vous pouvez également consulter un exemple de cette réponse:
DynamoDB JsonMarshaller ne peut pas désérialiser la liste d'objets
Merci. L'utilisation de @DynamoDBTypeConvertedJson a fonctionné pour mon cas ici
Pour marquer une autre classe comme faisant partie du modèle de données pour DynamoDBMapper, vous pouvez l'annoter avec @DynamoDBDocument
, qui indique à DynamoDBMapper qu'une classe peut être sérialisée en tant que document DynamoDB.
Pour les classes que vous n'êtes pas écriture (c'est-à-dire à partir de la bibliothèque Java ou d'une bibliothèque externe) ou si vous avez besoin de plus de contrôle sur la façon de sérialiser l'une de vos propres classes, vous pouvez utiliser @DynamoDBTypeConverted
, qui vous permet de mappez des données arbitraires en fournissant vos propres DynamoDBTypeConverter
implémentation n pour convertir n'importe quel objet Java en n'importe quel type DynamoDB pris en charge.
À l'aide de votre exemple de code, j'ai ajouté le code @DynamoDBDocument
et @DynamoDBTypeConverted > des annotations, ainsi qu'un exemple d'implémentation d'un
DynamoDBTypeConverter
qui convertit un Instant
en une String
ISO-8601. Si employeeId
est la clé de hachage de votre table, assurez-vous d'ajouter également l'annotation @DynamoDBHashKey
à 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); } }
CA aide. Merci. Je viens d'ajouter @DynamoDBTypeConvertedJson au lieu d'utiliser uniquement le @DynamoDBAttribute (attributeName = "EmployeeLevelDataRecords") public EmployeeLevelTrail employeeLevelTrail
Haha, j'ai oublié @DynamoDBTypeConvertedJson
lorsque j'écrivais ma réponse. Si cela fonctionne pour vous, faites une réponse en l'expliquant et acceptez-la afin que les autres puissent voir comment vous l'avez résolue.
L'annotation @DynamoDBTypeConvertedJson ne m'aide pas dans la mise à jour car je suis coincé dans l'erreur ci-dessous com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappi ngException: EmployeeData [EmployeeLevelTrail]; n'a pas pu annuler la conversion de l'attribut Ressemble. Je vais devoir écrire un convertisseur personnalisé pour ce cas
Pouvez-vous fournir toute la trace de la pile? Je ne serais pas surpris si la cause initiale est que le Instant
ne peut pas être désérialisé. Si tel est le cas, c'est parce que Jackson ObjectMapper (que DynamoDBTypeConvertedJson utilise) ne prend pas par défaut en charge la bibliothèque de temps Java 8. La réponse que j'ai donnée n'aura pas le même problème.
J'ai atteint la solution en utilisant le code ci-dessous. Avec uniquement @DynamoDBTypeConvertedJSON, j'ai pu créer une entrée dans la table mais ne pas la mettre à jour car je me heurtais à une exception de mappage Dynamo DB.
@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)); } }
La lecture de la documentation sur la façon de faire le mappage a aidé.