Utiliser des extensions pour personnaliser les opérations du client DynamoDB Enhanced - AWS SDK for Java 2.x

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Utiliser des extensions pour personnaliser les opérations du client DynamoDB Enhanced

L'API DynamoDB Enhanced Client prend en charge les extensions de plug-in qui fournissent des fonctionnalités allant au-delà des opérations de mappage. Les extensions utilisent deux méthodes hook pour modifier les données lors des opérations de lecture et d'écriture :

  • beforeWrite()- Modifie une opération d'écriture avant qu'elle ne se produise

  • afterRead()- Modifie les résultats d'une opération de lecture après qu'elle se soit produite

Certaines opérations (telles que les mises à jour d'éléments) effectuent à la fois une écriture puis une lecture. Les deux méthodes hook sont donc appelées.

Comment les extensions sont chargées

Les extensions sont chargées dans l'ordre que vous spécifiez dans le générateur de clients amélioré. L'ordre de chargement peut être important car une extension peut agir sur des valeurs transformées par une extension précédente.

Par défaut, le client amélioré charge deux extensions :

Vous pouvez modifier le comportement par défaut à l'aide du générateur de clients amélioré et charger n'importe quelle extension. Vous pouvez également n'en spécifier aucune si vous ne souhaitez pas utiliser les extensions par défaut.

Important

Si vous chargez vos propres extensions, le client amélioré ne charge aucune extension par défaut. Si vous souhaitez obtenir le comportement fourni par l'une ou l'autre des extensions par défaut, vous devez l'ajouter explicitement à la liste des extensions.

L'exemple suivant montre comment charger une extension personnalisée nommée d'verifyChecksumExtensionaprès leVersionedRecordExtension. Le n'AtomicCounterExtensionest pas chargé dans cet exemple.

DynamoDbEnhancedClientExtension versionedRecordExtension = VersionedRecordExtension.builder().build(); DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(dynamoDbClient) .extensions(versionedRecordExtension, verifyChecksumExtension) .build();

Détails et configuration des extensions disponibles

Les sections suivantes fournissent des informations détaillées sur chaque extension disponible dans le SDK.

Mettez en œuvre un verrouillage optimiste avec le VersionedRecordExtension

L'VersionedRecordExtensionextension permet un verrouillage optimiste en incrémentant et en suivant le numéro de version d'un élément au fur et à mesure que les éléments sont écrits dans la base de données. Une condition est ajoutée à chaque écriture qui entraîne l'échec de l'écriture si le numéro de version de l'élément persistant réel ne correspond pas à la valeur lue pour la dernière fois par l'application.

Configuration

Pour spécifier l'attribut à utiliser pour suivre le numéro de version de l'article, balisez un attribut numérique dans le schéma du tableau.

L'extrait suivant indique que l'versionattribut doit contenir le numéro de version de l'article.

@DynamoDbVersionAttribute public Integer getVersion() {...}; public void setVersion(Integer version) {...};

L'approche équivalente du schéma de table statique est illustrée dans l'extrait suivant.

.addAttribute(Integer.class, a -> a.name("version") .getter(Customer::getVersion) .setter(Customer::setVersion) // Apply the 'version' tag to the attribute. .tags(VersionedRecordExtension.AttributeTags.versionAttribute())

Comment ça marche

Le verrouillage optimiste avec le VersionedRecordExtension a l'impact suivant sur ces derniers DynamoDbEnhancedClient et sur DynamoDbTable les méthodes :

putItem

Une valeur de version initiale de 0 est attribuée aux nouveaux éléments. Cela peut être configuré avec@DynamoDbVersionAttribute(startAt = X).

updateItem

Si vous récupérez un élément, mettez à jour une ou plusieurs de ses propriétés et tentez d'enregistrer les modifications, l'opération n'aboutit que si le numéro de version côté client et côté serveur correspondent.

En cas de succès, le numéro de version est automatiquement incrémenté de 1. Cela peut être configuré avec@DynamoDbVersionAttribute(incrementBy = X).

deleteItem

L'DynamoDbVersionAttributeannotation n'a aucun effet. Vous devez ajouter une expression de condition manuellement lorsque vous supprimez un élément.

L'exemple suivant ajoute une expression conditionnelle pour garantir que l'élément supprimé est bien celui qui a été lu. Dans l'exemple suivant, recordVersion l'attribut du bean est annoté avec@DynamoDbVersionAttribute.

// 1. Read the item and get its current version. Customer item = customerTable.getItem(Key.builder().partitionValue("someId").build()); // `recordVersion` is the bean's attribute that is annotated with `@DynamoDbVersionAttribute`. AttributeValue currentVersion = item.getRecordVersion(); // 2. Create conditional delete with the `currentVersion` value. DeleteItemEnhancedRequest deleteItemRequest = DeleteItemEnhancedRequest.builder() .key(KEY) .conditionExpression(Expression.builder() .expression("recordVersion = :current_version_value") .putExpressionValue(":current_version_value", currentVersion) .build()).build(); customerTable.deleteItem(deleteItemRequest);
transactWriteItems
  • addPutItem: Cette méthode a le même comportement queputItem.

  • addUpdateItem: Cette méthode a le même comportement queupdateItem.

  • addDeleteItem: Cette méthode a le même comportement quedeleteItem.

batchWriteItem
  • addPutItem: Cette méthode a le même comportement queputItem.

  • addDeleteItem: Cette méthode a le même comportement quedeleteItem.

Note

Les tables globales DynamoDB utilisent une réconciliation « le dernier rédacteur gagne » entre les mises à jour simultanées, DynamoDB faisant de son mieux pour déterminer le dernier rédacteur. Si vous utilisez des tables globales, cette règle du « dernier rédacteur gagne » signifie que les stratégies de verrouillage risquent de ne pas fonctionner comme prévu, car toutes les répliques finiront par converger en fonction de la dernière écriture déterminée par DynamoDB.

Comment désactiver

Pour désactiver le verrouillage optimiste, n'utilisez pas l'@DynamoDbVersionAttributeannotation.

Implémentez des compteurs avec le AtomicCounterExtension

L'AtomicCounterExtensionextension incrémente un attribut numérique balisé chaque fois qu'un enregistrement est écrit dans la base de données. Vous pouvez spécifier des valeurs de départ et d'incrémentation. Si aucune valeur n'est spécifiée, la valeur de départ est définie sur 0 et la valeur de l'attribut augmente de 1.

Configuration

Pour spécifier quel attribut est un compteur, balisez un attribut de type Long dans le schéma du tableau.

L'extrait suivant montre l'utilisation des valeurs de début et d'incrément par défaut pour l'attribut. counter

@DynamoDbAtomicCounter public Long getCounter() {...}; public void setCounter(Long counter) {...};

L'approche du schéma de table statique est illustrée dans l'extrait suivant. L'extension du compteur atomique utilise une valeur de départ de 10 et augmente la valeur de 5 à chaque fois que l'enregistrement est écrit.

.addAttribute(Integer.class, a -> a.name("counter") .getter(Customer::getCounter) .setter(Customer::setCounter) // Apply the 'atomicCounter' tag to the attribute with start and increment values. .tags(StaticAttributeTags.atomicCounter(10L, 5L))

Ajoutez des horodatages avec le AutoGeneratedTimestampRecordExtension

L'AutoGeneratedTimestampRecordExtensionextension met automatiquement à jour les attributs de type balisés Instant avec un horodatage actuel chaque fois que l'élément est écrit avec succès dans la base de données. Cette extension n'est pas chargée par défaut.

Configuration

Pour spécifier l'attribut à mettre à jour avec l'horodatage actuel, balisez-le dans le Instant schéma de la table.

L'lastUpdateattribut est la cible du comportement de l'extension dans l'extrait suivant. Notez l'exigence selon laquelle l'attribut doit être un Instant type.

@DynamoDbAutoGeneratedTimestampAttribute public Instant getLastUpdate() {...} public void setLastUpdate(Instant lastUpdate) {...}

L'approche équivalente du schéma de table statique est illustrée dans l'extrait suivant.

.addAttribute(Instant.class, a -> a.name("lastUpdate") .getter(Customer::getLastUpdate) .setter(Customer::setLastUpdate) // Applying the 'autoGeneratedTimestamp' tag to the attribute. .tags(AutoGeneratedTimestampRecordExtension.AttributeTags.autoGeneratedTimestampAttribute())

Générez un UUID avec le AutoGeneratedUuidExtension

L'AutoGeneratedUuidExtensionextension génère un UUID (identifiant unique universel) unique pour un attribut lorsqu'un nouvel enregistrement est écrit dans la base de données. Utilise la méthode Java JDK UUID.randomUUID () et s'applique aux attributs de type. java.lang.String Cette extension n'est pas chargée par défaut.

Configuration

L'uniqueIdattribut est la cible du comportement de l'extension dans l'extrait suivant.

@AutoGeneratedUuidExtension public String getUniqueId() {...} public void setUniqueId(String uniqueId) {...}

L'approche équivalente du schéma de table statique est illustrée dans l'extrait suivant.

.addAttribute(String.class, a -> a.name("uniqueId") .getter(Customer::getUniqueId) .setter(Customer::setUniqueId) // Applying the 'autoGeneratedUuid' tag to the attribute. .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute())

Si vous souhaitez que l'extension renseigne l'UUID uniquement pour les putItem méthodes et non pour les updateItem méthodes, ajoutez l'annotation du comportement de mise à jour comme indiqué dans l'extrait suivant.

@AutoGeneratedUuidExtension @DynamoDbUpdateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS) public String getUniqueId() {...} public void setUniqueId(String uniqueId) {...}

Si vous utilisez l'approche du schéma de table statique, utilisez le code équivalent suivant.

.addAttribute(String.class, a -> a.name("uniqueId") .getter(Customer::getUniqueId) .setter(Customer::setUniqueId) // Applying the 'autoGeneratedUuid' tag to the attribute. .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute(), StaticAttributeTags.updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS))