Usa le estensioni per personalizzare le operazioni di DynamoDB Enhanced Client - AWS SDK for Java 2.x

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Usa le estensioni per personalizzare le operazioni di DynamoDB Enhanced Client

L'API DynamoDB Enhanced Client supporta le estensioni dei plugin che forniscono funzionalità che vanno oltre le operazioni di mappatura. Le estensioni utilizzano due metodi hook per modificare i dati durante le operazioni di lettura e scrittura:

  • beforeWrite()- Modifica un'operazione di scrittura prima che avvenga

  • afterRead()- Modifica i risultati di un'operazione di lettura dopo che è avvenuta

Alcune operazioni (come l'aggiornamento degli elementi) eseguono sia una scrittura che una lettura, quindi vengono chiamati entrambi i metodi hook.

Come vengono caricate le estensioni

Le estensioni vengono caricate nell'ordine specificato nel generatore di client avanzato. L'ordine di caricamento può essere importante perché un'estensione può agire su valori che sono stati trasformati da un'estensione precedente.

Per impostazione predefinita, il client avanzato carica due estensioni:

È possibile sovrascrivere il comportamento predefinito con il client builder avanzato e caricare qualsiasi estensione. Puoi anche specificarne nessuna se non desideri le estensioni predefinite.

Importante

Se carichi le tue estensioni, il client avanzato non carica alcuna estensione predefinita. Se desideri il comportamento fornito da una delle estensioni predefinite, devi aggiungerla esplicitamente all'elenco delle estensioni.

L'esempio seguente mostra come caricare un'estensione personalizzata che verifyChecksumExtension prende il VersionedRecordExtension nome da. In questo esempio non AtomicCounterExtension viene caricato.

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

Dettagli e configurazione delle estensioni disponibili

Le seguenti sezioni forniscono informazioni dettagliate su ciascuna estensione disponibile nell'SDK.

Implementa il blocco ottimistico con VersionedRecordExtension

L'VersionedRecordExtensionestensione fornisce un blocco ottimistico incrementando e tracciando il numero di versione di un articolo man mano che gli articoli vengono scritti nel database. A ogni scrittura viene aggiunta una condizione che causa l'esito negativo della scrittura se il numero di versione dell'elemento persistente effettivo non corrisponde al valore letto per l'ultima volta dall'applicazione.

Configurazione

Per specificare l'attributo da utilizzare per tenere traccia del numero di versione dell'elemento, contrassegnate un attributo numerico nello schema della tabella.

Il frammento seguente specifica che l'versionattributo deve contenere il numero di versione dell'articolo.

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

L'approccio equivalente allo schema di tabella statica è illustrato nel frammento seguente.

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

Come funziona

Il blocco ottimistico con il VersionedRecordExtension ha il seguente impatto su questi metodi: DynamoDbEnhancedClient DynamoDbTable

putItem

Ai nuovi elementi viene assegnato un valore di versione iniziale pari a 0. Questo può essere configurato con@DynamoDbVersionAttribute(startAt = X).

updateItem

Se recuperate un elemento, aggiornate una o più delle sue proprietà e tentate di salvare le modifiche, l'operazione ha esito positivo solo se il numero di versione sul lato client e sul lato server corrisponde.

In caso di successo, il numero di versione viene automaticamente incrementato di 1. Questo può essere configurato con@DynamoDbVersionAttribute(incrementBy = X).

deleteItem

L'DynamoDbVersionAttributeannotazione non ha effetto. È necessario aggiungere manualmente un'espressione di condizione quando si elimina un elemento.

L'esempio seguente aggiunge un'espressione condizionale per garantire che l'elemento eliminato sia quello che è stato letto. Nell'esempio seguente l'attributo del bean recordVersion è annotato con. @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: Questo metodo ha lo stesso comportamento diputItem.

  • addUpdateItem: Questo metodo ha lo stesso comportamento diupdateItem.

  • addDeleteItem: Questo metodo ha lo stesso comportamento dideleteItem.

batchWriteItem
  • addPutItem: Questo metodo ha lo stesso comportamento diputItem.

  • addDeleteItem: Questo metodo ha lo stesso comportamento dideleteItem.

Nota

Le tabelle globali di DynamoDB utilizzano una riconciliazione «last writer win» tra aggiornamenti simultanei, in cui DynamoDB fa del suo meglio per determinare l'ultimo writer. Se si utilizzano tabelle globali, questa politica «l'ultimo scrittore vince» significa che le strategie di blocco potrebbero non funzionare come previsto, poiché tutte le repliche alla fine convergeranno in base all'ultima scrittura determinata da DynamoDB.

Come disattivare

Per disabilitare il blocco ottimistico, non utilizzare l'@DynamoDbVersionAttributeannotazione.

Implementa i contatori con AtomicCounterExtension

L'AtomicCounterExtensionestensione incrementa un attributo numerico con tag ogni volta che un record viene scritto nel database. È possibile specificare valori iniziali e incrementali. Se non viene specificato alcun valore, il valore iniziale viene impostato su 0 e il valore dell'attributo aumenta di 1.

Configurazione

Per specificare quale attributo è un contatore, contrassegnate un attributo di tipo Long nello schema della tabella.

Il frammento seguente mostra l'uso dei valori di inizio e incremento predefiniti per l'attributo. counter

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

L'approccio allo schema di tabella statica è illustrato nel frammento seguente. L'estensione del contatore atomico utilizza un valore iniziale di 10 e incrementa il valore di 5 ogni volta che viene scritto il record.

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

Aggiungi timestamp con AutoGeneratedTimestampRecordExtension

L'AutoGeneratedTimestampRecordExtensionestensione aggiorna automaticamente gli attributi di tipo contrassegnati Instant con un timestamp corrente ogni volta che l'elemento viene scritto correttamente nel database. Questa estensione non viene caricata per impostazione predefinita.

Configurazione

Per specificare l'attributo da aggiornare con il timestamp corrente, contrassegnate l'Instantattributo nello schema della tabella.

L'lastUpdateattributo è l'obiettivo del comportamento dell'estensione nel frammento seguente. Nota il requisito secondo cui l'attributo deve essere di Instant tipo.

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

L'approccio equivalente allo schema di tabella statica è illustrato nel frammento seguente.

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

Genera un UUID con AutoGeneratedUuidExtension

L'AutoGeneratedUuidExtensionestensione genera un UUID (Universally Unique Identifier) univoco per un attributo quando un nuovo record viene scritto nel database. Utilizza il metodo Java JDK UUID.randomUUID () e si applica agli attributi di tipo. java.lang.String Questa estensione non viene caricata per impostazione predefinita.

Configurazione

L'uniqueIdattributo è l'obiettivo del comportamento dell'estensione nel frammento seguente.

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

L'approccio equivalente allo schema di tabella statica è illustrato nel frammento seguente.

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

Se desideri che l'estensione compili l'UUID solo per i putItem metodi e non per i updateItem metodi, aggiungi l'annotazione sul comportamento di aggiornamento come mostrato nel seguente frammento.

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

Se utilizzate l'approccio dello schema a tabella statica, utilizzate il seguente codice equivalente.

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