3
votes

Annotation DynamoDB Mapper pour un objet contenant la liste d'un autre objet

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


0 commentaires

3 Réponses :


0
votes

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).

https://docs.aws.amazon.com /amazondynamodb/latest/developerguide/DynamoDBMapper.ArbitraryDataMapping.html

Vous pouvez également consulter un exemple de cette réponse:

DynamoDB JsonMarshaller ne peut pas désérialiser la liste d'objets


1 commentaires

Merci. L'utilisation de @DynamoDBTypeConvertedJson a fonctionné pour mon cas ici



5
votes

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


4 commentaires

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.



1
votes

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é.


0 commentaires