

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
<a name="ddb-en-client-extensions"></a>

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
<a name="ddb-en-client-extensions-loading"></a>

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:
+ `[VersionedRecordExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/VersionedRecordExtension.html)`- Fornisce un blocco ottimistico
+ `[AtomicCounterExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/AtomicCounterExtension.html)`- Incrementa automaticamente gli attributi del contatore

È 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
<a name="ddb-en-client-extensions-details"></a>

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

### Implementa il blocco ottimistico con `VersionedRecordExtension`
<a name="ddb-en-client-extensions-VRE"></a>

L'`VersionedRecordExtension`estensione 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
<a name="ddb-en-client-extensions-VRE-conf"></a>

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'`version`attributo 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
<a name="ddb-en-client-extensions-VRE-how-it-works"></a>

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'`DynamoDbVersionAttribute`annotazione 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 di`putItem`.
+ `addUpdateItem`: Questo metodo ha lo stesso comportamento di`updateItem`.
+ `addDeleteItem`: Questo metodo ha lo stesso comportamento di`deleteItem`.

**`batchWriteItem`**  
+ `addPutItem`: Questo metodo ha lo stesso comportamento di`putItem`.
+ `addDeleteItem`: Questo metodo ha lo stesso comportamento di`deleteItem`.

**Nota**  
Le tabelle globali di DynamoDB utilizzano [una riconciliazione «last writer win»](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html#V2globaltables_HowItWorks.consistency-modes) 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
<a name="ddb-en-client-extensions-VRE-how-to-disable"></a>

Per disabilitare il blocco ottimistico, non utilizzare l'`@DynamoDbVersionAttribute`annotazione.

### Implementa i contatori con `AtomicCounterExtension`
<a name="ddb-en-client-extensions-ACE"></a>

L'`AtomicCounterExtension`estensione 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
<a name="ddb-en-client-extensions-ACE-conf"></a>

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`
<a name="ddb-en-client-extensions-AGTE"></a>

L'`AutoGeneratedTimestampRecordExtension`estensione aggiorna automaticamente gli attributi di tipo contrassegnati `[Instant](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html)` con un timestamp corrente ogni volta che l'elemento viene scritto correttamente nel database. Questa estensione non viene caricata per impostazione predefinita.

#### Configurazione
<a name="ddb-en-client-extensions-AGTE-conf"></a>

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

L'`lastUpdate`attributo è 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
<a name="ddb-en-client-extensions-AGUE"></a>

L'`AutoGeneratedUuidExtension`estensione 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](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--) () e si applica agli attributi di tipo. `java.lang.String` Questa estensione non viene caricata per impostazione predefinita.

#### Configurazione
<a name="ddb-en-client-extensions-AGUE-conf"></a>

L'`uniqueId`attributo è 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](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html) 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))
```

# Esempio di estensione personalizzata
<a name="ddb-en-client-extensions-custom"></a>

È possibile creare estensioni personalizzate implementando l'`DynamoDbEnhancedClientExtension`interfaccia. La seguente classe di estensione personalizzata mostra un `beforeWrite()` metodo che utilizza un'espressione di aggiornamento per impostare un `registrationDate` attributo se l'elemento nel database non ne ha già uno.

```
public final class CustomExtension implements DynamoDbEnhancedClientExtension {

    // 1. In a custom extension, use an UpdateExpression to define what action to take before
    //    an item is updated.
    @Override
    public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite context) {
        if ( context.operationContext().tableName().equals("Customer")
                && context.operationName().equals(OperationName.UPDATE_ITEM)) {
            return WriteModification.builder()
                    .updateExpression(createUpdateExpression())
                    .build();
        }
        return WriteModification.builder().build();  // Return an "empty" WriteModification instance if the extension should not be applied.
                                                     // In this case, if the code is not updating an item on the Customer table.
    }

    private static UpdateExpression createUpdateExpression() {

        // 2. Use a SetAction, a subclass of UpdateAction, to provide the values in the update.
        SetAction setAction =
                SetAction.builder()
                        .path("registrationDate")
                        .value("if_not_exists(registrationDate, :regValue)")
                        .putExpressionValue(":regValue", AttributeValue.fromS(Instant.now().toString()))
                        .build();
        // 3. Build the UpdateExpression with one or more UpdateAction.
        return UpdateExpression.builder()
                .addAction(setAction)
                .build();
    }
}
```