

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Verwenden Sie Erweiterungen, um DynamoDB Enhanced Client-Operationen anzupassen
<a name="ddb-en-client-extensions"></a>

Die DynamoDB Enhanced Client API unterstützt Plugin-Erweiterungen, die Funktionen bieten, die über Mapping-Operationen hinausgehen. Erweiterungen verwenden zwei Hook-Methoden, um Daten während Lese- und Schreibvorgängen zu ändern:
+ `beforeWrite()`- Ändert einen Schreibvorgang, bevor er stattfindet
+ `afterRead()`- Ändert die Ergebnisse eines Lesevorgangs, nachdem er ausgeführt wurde

Bei einigen Operationen (wie Artikelaktualisierungen) wird sowohl ein Schreib- als auch ein Lesevorgang ausgeführt, sodass beide Hook-Methoden aufgerufen werden.

## Wie werden Erweiterungen geladen
<a name="ddb-en-client-extensions-loading"></a>

Erweiterungen werden in der Reihenfolge geladen, die Sie im erweiterten Client Builder angegeben haben. Die Ladereihenfolge kann wichtig sein, da eine Erweiterung auf Werte reagieren kann, die durch eine vorherige Erweiterung transformiert wurden.

Standardmäßig lädt der erweiterte Client zwei Erweiterungen:
+ `[VersionedRecordExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/VersionedRecordExtension.html)`- Sorgt für optimistisches Sperren
+ `[AtomicCounterExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/AtomicCounterExtension.html)`- Inkrementiert automatisch die Zählerattribute

Sie können das Standardverhalten mit dem erweiterten Client Builder überschreiben und jede Erweiterung laden. Sie können auch keine angeben, wenn Sie die Standarderweiterungen nicht verwenden möchten.

**Wichtig**  
Wenn Sie Ihre eigenen Erweiterungen laden, lädt der erweiterte Client keine Standarderweiterungen. Wenn Sie das Verhalten einer der Standarderweiterungen verwenden möchten, müssen Sie sie explizit zur Liste der Erweiterungen hinzufügen.

Das folgende Beispiel zeigt, wie eine benutzerdefinierte Erweiterung geladen wird, die `verifyChecksumExtension` nach dem benannt ist`VersionedRecordExtension`. Die `AtomicCounterExtension` ist in diesem Beispiel nicht geladen.

```
DynamoDbEnhancedClientExtension versionedRecordExtension = VersionedRecordExtension.builder().build();

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

## Verfügbare Erweiterungsdetails und Konfiguration
<a name="ddb-en-client-extensions-details"></a>

Die folgenden Abschnitte enthalten detaillierte Informationen zu jeder verfügbaren Erweiterung im SDK.

### Implementieren Sie optimistisches Sperren mit dem `VersionedRecordExtension`
<a name="ddb-en-client-extensions-VRE"></a>

Die `VersionedRecordExtension` Erweiterung ermöglicht optimistisches Sperren, indem die Versionsnummer eines Elements beim Schreiben von Elementen in die Datenbank erhöht und nachverfolgt wird. Jedem Schreibvorgang wird eine Bedingung hinzugefügt, die dazu führt, dass der Schreibvorgang fehlschlägt, wenn die Versionsnummer des tatsächlich persistenten Elements nicht dem Wert entspricht, den die Anwendung zuletzt gelesen hat.

#### Konfiguration
<a name="ddb-en-client-extensions-VRE-conf"></a>

Um anzugeben, welches Attribut verwendet werden soll, um die Versionsnummer des Elements nachzuverfolgen, kennzeichnen Sie ein numerisches Attribut im Tabellenschema.

Der folgende Codeausschnitt gibt an, dass das `version` Attribut die Versionsnummer des Artikels enthalten soll.

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

Der entsprechende Ansatz für ein statisches Tabellenschema wird im folgenden Codeausschnitt dargestellt.

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

#### Funktionsweise
<a name="ddb-en-client-extensions-VRE-how-it-works"></a>

Das optimistische Sperren mit dem `VersionedRecordExtension` hat folgende Auswirkungen auf diese `DynamoDbEnhancedClient` und `DynamoDbTable` Methoden:

**`putItem`**  
Neuen Elementen wird der ursprüngliche Versionswert 0 zugewiesen. Dies kann mit konfiguriert werden`@DynamoDbVersionAttribute(startAt = X)`.

**`updateItem`**  
Wenn Sie ein Element abrufen, eine oder mehrere seiner Eigenschaften aktualisieren und versuchen, die Änderungen zu speichern, ist der Vorgang nur erfolgreich, wenn die Versionsnummer auf der Client- und der Serverseite übereinstimmen.  
Bei Erfolg wird die Versionsnummer automatisch um 1 erhöht. Dies kann mit `@DynamoDbVersionAttribute(incrementBy = X)` konfiguriert werden.

**`deleteItem`**  
Die `DynamoDbVersionAttribute` Anmerkung hat keine Auswirkung. Sie müssen beim Löschen eines Elements manuell Bedingungsausdrücke hinzufügen.  
Im folgenden Beispiel wird ein bedingter Ausdruck hinzugefügt, um sicherzustellen, dass es sich bei dem gelöschten Element auch um das gelesene Element handelt. Im folgenden Beispiel `recordVersion` ist das Attribut der Bean mit `@DynamoDbVersionAttribute` annotiert.  

```
// 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`: Diese Methode hat das gleiche Verhalten wie`putItem`.
+ `addUpdateItem`: Diese Methode hat das gleiche Verhalten wie`updateItem`.
+ `addDeleteItem`: Diese Methode hat das gleiche Verhalten wie`deleteItem`.

**`batchWriteItem`**  
+ `addPutItem`: Diese Methode hat das gleiche Verhalten wie`putItem`.
+ `addDeleteItem`: Diese Methode hat das gleiche Verhalten wie`deleteItem`.

**Anmerkung**  
Globale DynamoDB-Tabellen verwenden einen [Abgleich zwischen gleichzeitigen Aktualisierungen, bei dem DynamoDB sich nach besten Kräften bemüht, den letzten Writer](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html#V2globaltables_HowItWorks.consistency-modes) zu ermitteln. Wenn Sie globale Tabellen verwenden, bedeutet diese „Last Writer gewinnt“ -Richtlinie, dass Sperrstrategien möglicherweise nicht wie erwartet funktionieren, da alle Replikate letztendlich auf der Grundlage des von DynamoDB bestimmten letzten Schreibvorgangs konvergieren. 

#### Wie deaktiviere ich
<a name="ddb-en-client-extensions-VRE-how-to-disable"></a>

Verwenden Sie die `@DynamoDbVersionAttribute` Anmerkung nicht, um das optimistische Sperren zu deaktivieren.

### Implementieren Sie Zähler mit dem `AtomicCounterExtension`
<a name="ddb-en-client-extensions-ACE"></a>

Die `AtomicCounterExtension` Erweiterung erhöht jedes Mal, wenn ein Datensatz in die Datenbank geschrieben wird, ein mit Tags versehenes numerisches Attribut. Sie können Start- und Inkrementwerte angeben. Wenn keine Werte angegeben sind, wird der Startwert auf 0 gesetzt und der Wert des Attributs wird um 1 erhöht.

#### Konfiguration
<a name="ddb-en-client-extensions-ACE-conf"></a>

Um anzugeben, welches Attribut ein Zähler ist, kennzeichnen Sie ein Attribut vom Typ `Long` im Tabellenschema.

Der folgende Ausschnitt zeigt die Verwendung der standardmäßigen Start- und Inkrementwerte für das Attribut. `counter`

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

Der Ansatz eines statischen Tabellenschemas wird im folgenden Codeausschnitt dargestellt. Die Atomic Counter Extension verwendet einen Startwert von 10 und erhöht den Wert jedes Mal, wenn der Datensatz geschrieben wird, um 5.

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

### Fügen Sie Zeitstempel hinzu mit `AutoGeneratedTimestampRecordExtension`
<a name="ddb-en-client-extensions-AGTE"></a>

Die `AutoGeneratedTimestampRecordExtension` Erweiterung aktualisiert jedes Mal, wenn das Element erfolgreich in die Datenbank geschrieben wurde, automatisch markierte Attribute des Typs `[Instant](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html)` mit einem aktuellen Zeitstempel. Diese Erweiterung ist standardmäßig nicht geladen.

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

Um anzugeben, welches Attribut mit dem aktuellen Zeitstempel aktualisiert werden soll, kennzeichnen Sie das `Instant` Attribut im Tabellenschema.

Das `lastUpdate` Attribut ist das Ziel des Verhaltens der Erweiterung im folgenden Codeausschnitt. Beachten Sie die Anforderung, dass das Attribut ein `Instant` Typ sein muss.

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

Der entsprechende Ansatz für ein statisches Tabellenschema wird im folgenden Codeausschnitt dargestellt.

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

### Generieren Sie eine UUID mit dem AutoGeneratedUuidExtension
<a name="ddb-en-client-extensions-AGUE"></a>

Die `AutoGeneratedUuidExtension` Erweiterung generiert eine eindeutige UUID (Universally Unique Identifier) für ein Attribut, wenn ein neuer Datensatz in die Datenbank geschrieben wird. Verwendet die Java-JDK-Methode [UUID.randomUUID () und gilt für Typattribute](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--). `java.lang.String` Diese Erweiterung wird standardmäßig nicht geladen.

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

Das `uniqueId` Attribut ist das Ziel des Verhaltens der Erweiterung im folgenden Codeausschnitt.

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

Der entsprechende Ansatz für ein statisches Tabellenschema wird im folgenden Codeausschnitt dargestellt.

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

Wenn Sie möchten, dass die Erweiterung die UUID nur für `putItem` Methoden und nicht für Methoden auffüllt, fügen Sie die Anmerkung zum `updateItem` [Aktualisierungsverhalten](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html) hinzu, wie im folgenden Codeausschnitt gezeigt.

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

Wenn Sie den Ansatz eines statischen Tabellenschemas verwenden, verwenden Sie den folgenden äquivalenten Code.

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

# Beispiel für eine benutzerdefinierte Erweiterung
<a name="ddb-en-client-extensions-custom"></a>

Sie können benutzerdefinierte Erweiterungen erstellen, indem Sie die `DynamoDbEnhancedClientExtension` Schnittstelle implementieren. Die folgende benutzerdefinierte Erweiterungsklasse zeigt eine `beforeWrite()` Methode, die einen Aktualisierungsausdruck verwendet, um ein `registrationDate` Attribut festzulegen, falls das Element in der Datenbank noch keines hat.

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