

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.

# Arbeite mit DynamoDB
<a name="examples-dynamodb"></a>

[DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) ist ein vollständig verwalteter NoSQL-Datenbankdienst, der schnelle und vorhersehbare Leistung mit nahtloser Skalierbarkeit bietet. In diesem Abschnitt erfahren Sie, wie Sie mit DynamoDB unter Verwendung von 2.x arbeiten. AWS SDK für Java 

## Wählen Sie Ihren DynamoDB-Client
<a name="ddb-clients-overview"></a>

Das SDK bietet zwei Hauptansätze für die Arbeit mit DynamoDB:

Low-Level-Client (`DynamoDbClient`)  
Bietet direkten Zugriff auf DynamoDB-Operationen mit voller Kontrolle über Anfragen und Antworten. Verwenden Sie diesen Client, wenn Sie eine detaillierte Steuerung benötigen oder mit dynamischen Schemas arbeiten möchten.

Verbesserter Client () `DynamoDbEnhancedClient`  
Bietet objektorientierte Programmierung mit automatischer Zuordnung zwischen Java-Objekten und DynamoDB-Elementen. Bietet außerdem dokumentenorientierte Funktionen für die Arbeit mit JSON-ähnlichen Daten, die keinem festen Schema folgen. Verwenden Sie diesen Client, wenn Sie mit klar definierten Datenmodellen oder dokumentartigen Daten arbeiten.

## DynamoDB-Clients konfigurieren
<a name="ddb-configuration-setup"></a>

Bevor Sie mit DynamoDB arbeiten, konfigurieren Sie Ihren Client für optimale Leistung und Zuverlässigkeit.

### Das Wiederholungsverhalten von DynamoDB verstehen
<a name="ddb-retry-behavior"></a>

DynamoDB-Clients verwenden standardmäßig eine maximale Anzahl von Wiederholungsversuchen von 8, was höher ist als bei anderen Clients. AWS-Service Diese höhere Anzahl an Wiederholungen hilft dabei, den verteilten Charakter von DynamoDB und die vorübergehenden Kapazitätsbeschränkungen zu bewältigen. Weitere Informationen zu Wiederholungsstrategien finden Sie unter. [Konfigurieren Sie das Wiederholungsverhalten in der AWS SDK for Java 2.x](retry-strategy.md)

### Optimieren Sie die Leistung mit kontobasierten Endpunkten
<a name="ddb-account-based-endpoints-v2"></a>

DynamoDB bietet [AWS kontobasierte Endpunkte](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.SDKOverview.html#Programming.SDKs.endpoints), die die Leistung verbessern, indem sie Ihre AWS Konto-ID verwenden, um die Anforderungsweiterleitung zu optimieren. 

Um diese Funktion nutzen zu können, benötigen Sie Version 2.28.4 oder höher von. AWS SDK for Java 2.x Sie finden die neueste Version im zentralen [Maven-Repository](https://central.sonatype.com/artifact/software.amazon.awssdk/bom/versions). Unterstützte SDK-Versionen verwenden automatisch die neuen Endpunkte.

Wählen Sie eine der folgenden Optionen, um das kontobasierte Routing zu deaktivieren:
+ Konfigurieren Sie einen DynamoDB-Dienstclient mit der `AccountIdEndpointMode` Einstellung auf. `DISABLED`
+ Legen Sie eine Umgebungsvariable fest.
+ Legen Sie eine JVM-Systemeigenschaft fest.
+ Aktualisieren Sie die Einstellung für die gemeinsam genutzte AWS Konfigurationsdatei.

Das folgende Beispiel zeigt, wie Sie das kontobasierte Routing deaktivieren, indem Sie einen DynamoDB-Dienstclient konfigurieren:

```
DynamoDbClient.builder()
                 .accountIdEndpointMode(AccountIdEndpointMode.DISABLED)
                 .build();
```

Weitere Informationen zu den anderen Konfigurationsoptionen finden Sie unter [Account-based Endpoints](https://docs.aws.amazon.com/sdkref/latest/guide/feature-account-endpoints.html) im Referenzhandbuch und im Tools-Referenzhandbuch. AWS SDKs 

## Was wird in diesem Thema behandelt
<a name="ddb-topics-overview"></a>

In den folgenden Abschnitten erfahren Sie, wie Sie mit DynamoDB arbeiten:
+ [Arbeiten Sie mit Tabellen in DynamoDB](examples-dynamodb-tables.md)- Tabellen erstellen, beschreiben, aktualisieren und löschen
+ [Arbeiten Sie mit Artikeln in DynamoDB](examples-dynamodb-items.md)- Einzelne Elemente hinzufügen, abrufen und aktualisieren
+ [Ordnen Sie Java-Objekte DynamoDB-Elementen zu mit dem AWS SDK for Java 2.x](dynamodb-enhanced-client.md)- Verwenden Sie Objektzuordnungen und dokumentenorientierte Daten mit dem Enhanced Client

Weitere DynamoDB-Codebeispiele finden Sie unter [DynamoDB-Codebeispiele in der AWS Codebeispielbibliothek](java_dynamodb_code_examples.md).

# Arbeiten Sie mit Tabellen in DynamoDB
<a name="examples-dynamodb-tables"></a>

Tabellen sind die Container für alle Elemente in einer DynamoDB Datenbank. Bevor Sie Daten hinzufügen oder daraus entfernen können DynamoDB, müssen Sie eine Tabelle erstellen.

Für jede Tabelle definieren Sie:
+ Ein *Tabellenname*, der für Ihr Konto und Ihre Region eindeutig ist.
+ Einen *Primärschlüssel,* für den jeder Wert eindeutig sein muss. Ihre Tabelle kann keine zwei Elemente mit demselben Primärschlüsselwert enthalten.

  Ein Primärschlüssel kann *einfach* sein, also aus einem Schlüssel mit einer einzigen Partition (HASH) bestehen, oder *zusammengesetzt*, also aus einer Partition und einem Sortierschlüssel (RANGE).

  Jedem Schlüsselwert ist ein *Datentyp* zugeordnet, der nach der [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ScalarAttributeType.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ScalarAttributeType.html)Klasse aufgezählt wird. Der Schlüsselwert kann binär (B), numerisch (n) oder eine Zeichenfolge (S) sein. Weitere Informationen finden Sie unter [Benennungsregeln und Datentypen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) im Amazon DynamoDB Entwicklerhandbuch.
+  Der *bereitgestellte Durchsatz* gibt Werte an, die die Anzahl der reservierten Lese-Schreib-Kapazitätseinheiten für die Tabelle angeben.
**Anmerkung**  
Amazon DynamoDB Die [Preisgestaltung](https://aws.amazon.com/dynamodb/pricing/) basiert auf den bereitgestellten Durchsatzwerten, die Sie für Ihre Tabellen festlegen. Reservieren Sie daher nur so viel Kapazität, wie Sie für Ihre Tabelle voraussichtlich benötigen.

  Der bereitgestellte Durchsatz für eine Tabelle kann jederzeit geändert werden. So können Sie die Kapazität anpassen, wenn sich Ihre Anforderungen ändern.

## Erstellen einer Tabelle
<a name="dynamodb-create-table"></a>

Verwenden Sie die `DynamoDbClient’s` `createTable` Methode, um eine neue DynamoDB Tabelle zu erstellen. Sie müssen Tabellenattribute und ein Tabellenschema erstellen. Beide Komponenten fließen in den Primärschlüssel der Tabelle ein. Sie müssen auch anfänglich bereitgestellte Durchsatzwerte und einen Tabellennamen angeben.

**Anmerkung**  
Wenn eine Tabelle mit dem von Ihnen gewählten Namen bereits existiert, `[DynamoDbException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html)` wird a ausgelöst.

### Erstellen einer Tabelle mit einem einfachen Primärschlüssel
<a name="dynamodb-create-table-simple"></a>

Dieser Code erstellt eine Tabelle mit einem Attribut, das den einfachen Primärschlüssel der Tabelle darstellt. Das Beispiel verwendet `[KeySchemaElement](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/KeySchemaElement.html)` Objekte `[AttributeDefinition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeDefinition.html)` und für. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CreateTableRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CreateTableRequest.html)

 **Importe** 

```
import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
```

 **Code** 

```
    public static String createTable(DynamoDbClient ddb, String tableName, String key) {

        DynamoDbWaiter dbWaiter = ddb.waiter();
        CreateTableRequest request = CreateTableRequest.builder()
                .attributeDefinitions(AttributeDefinition.builder()
                        .attributeName(key)
                        .attributeType(ScalarAttributeType.S)
                        .build())
                .keySchema(KeySchemaElement.builder()
                        .attributeName(key)
                        .keyType(KeyType.HASH)
                        .build())
                .provisionedThroughput(ProvisionedThroughput.builder()
                        .readCapacityUnits(new Long(10))
                        .writeCapacityUnits(new Long(10))
                        .build())
                .tableName(tableName)
                .build();

        String newTable ="";
        try {
            CreateTableResponse response = ddb.createTable(request);
            DescribeTableRequest tableRequest = DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build();

            // Wait until the Amazon DynamoDB table is created
            WaiterResponse<DescribeTableResponse> waiterResponse =  dbWaiter.waitUntilTableExists(tableRequest);
            waiterResponse.matched().response().ifPresent(System.out::println);

            newTable = response.tableDescription().tableName();
            return newTable;

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
       return "";
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTable.java) finden Sie unter. GitHub

### Erstellen einer Tabelle mit einem zusammengesetzten Primärschlüssel
<a name="dynamodb-create-table-composite"></a>

Im folgenden Beispiel wird eine Tabelle mit zwei Attributen erstellt. Beide Attribute werden für den zusammengesetzten Primärschlüssel verwendet.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
```

 **Code** 

```
    public static String createTableComKey(DynamoDbClient ddb, String tableName) {
        CreateTableRequest request = CreateTableRequest.builder()
                .attributeDefinitions(
                        AttributeDefinition.builder()
                                .attributeName("Language")
                                .attributeType(ScalarAttributeType.S)
                                .build(),
                        AttributeDefinition.builder()
                                .attributeName("Greeting")
                                .attributeType(ScalarAttributeType.S)
                                .build())
                .keySchema(
                        KeySchemaElement.builder()
                                .attributeName("Language")
                                .keyType(KeyType.HASH)
                                .build(),
                        KeySchemaElement.builder()
                                .attributeName("Greeting")
                                .keyType(KeyType.RANGE)
                                .build())
                .provisionedThroughput(
                        ProvisionedThroughput.builder()
                                .readCapacityUnits(new Long(10))
                                .writeCapacityUnits(new Long(10)).build())
                .tableName(tableName)
                .build();

       String tableId = "";

       try {
            CreateTableResponse result = ddb.createTable(request);
            tableId = result.tableDescription().tableId();
            return tableId;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
       return "";
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTableCompositeKey.java) finden Sie unter GitHub.

## Auflisten von Tabellen
<a name="dynamodb-list-tables"></a>

Sie können die Tabellen in einer bestimmten Region auflisten, indem Sie die `DynamoDbClient’s` `listTables` Methode aufrufen.

**Anmerkung**  
Wenn die benannte Tabelle für Ihr Konto und Ihre Region nicht existiert, [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)wird a ausgelöst.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;
import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import java.util.List;
```

 **Code** 

```
    public static void listAllTables(DynamoDbClient ddb){

        boolean moreTables = true;
        String lastName = null;

        while(moreTables) {
            try {
                ListTablesResponse response = null;
                if (lastName == null) {
                    ListTablesRequest request = ListTablesRequest.builder().build();
                    response = ddb.listTables(request);
                } else {
                    ListTablesRequest request = ListTablesRequest.builder()
                            .exclusiveStartTableName(lastName).build();
                    response = ddb.listTables(request);
                }

                List<String> tableNames = response.tableNames();

                if (tableNames.size() > 0) {
                    for (String curName : tableNames) {
                        System.out.format("* %s\n", curName);
                    }
                } else {
                    System.out.println("No tables found!");
                    System.exit(0);
                }

                lastName = response.lastEvaluatedTableName();
                if (lastName == null) {
                    moreTables = false;
                }
            } catch (DynamoDbException e) {
                System.err.println(e.getMessage());
                System.exit(1);
            }
        }
        System.out.println("\nDone!");
    }
```

Standardmäßig werden bis zu 100 Tabellen pro Aufruf zurückgegeben. Verwenden Sie diese `lastEvaluatedTableName` Option für das zurückgegebene [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ListTablesResponse.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ListTablesResponse.html)Objekt, um die zuletzt ausgewertete Tabelle abzurufen. Mit diesem Wert können Sie die Auflistung nach dem zuletzt zurückgegebenen Wert der vorherigen Auflistung beginnen.

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/ListTables.java) finden Sie unter. GitHub

## Beschreiben (Abrufen von Informationen zu) einer Tabelle
<a name="dynamodb-describe-table"></a>

Verwenden Sie die `DynamoDbClient’s` `describeTable` Methode, um Informationen zu einer Tabelle abzurufen.

**Anmerkung**  
Wenn die benannte Tabelle für Ihr Konto und Ihre Region nicht existiert, [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)wird a ausgelöst.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughputDescription;
import software.amazon.awssdk.services.dynamodb.model.TableDescription;
import java.util.List;
```

 **Code** 

```
    public static void describeDymamoDBTable(DynamoDbClient ddb,String tableName ) {

        DescribeTableRequest request = DescribeTableRequest.builder()
                .tableName(tableName)
                .build();

        try {
            TableDescription tableInfo =
                    ddb.describeTable(request).table();

            if (tableInfo != null) {
                System.out.format("Table name  : %s\n",
                        tableInfo.tableName());
                System.out.format("Table ARN   : %s\n",
                        tableInfo.tableArn());
                System.out.format("Status      : %s\n",
                        tableInfo.tableStatus());
                System.out.format("Item count  : %d\n",
                        tableInfo.itemCount().longValue());
                System.out.format("Size (bytes): %d\n",
                        tableInfo.tableSizeBytes().longValue());

                ProvisionedThroughputDescription throughputInfo =
                        tableInfo.provisionedThroughput();
                System.out.println("Throughput");
                System.out.format("  Read Capacity : %d\n",
                        throughputInfo.readCapacityUnits().longValue());
                System.out.format("  Write Capacity: %d\n",
                        throughputInfo.writeCapacityUnits().longValue());

                List<AttributeDefinition> attributes =
                        tableInfo.attributeDefinitions();
                System.out.println("Attributes");

                for (AttributeDefinition a : attributes) {
                    System.out.format("  %s (%s)\n",
                            a.attributeName(), a.attributeType());
                }
            }
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        System.out.println("\nDone!");
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DescribeTable.java) finden Sie unter GitHub.

## Ändern (Aktualisieren) einer Tabelle
<a name="dynamodb-update-table"></a>

Sie können die bereitgestellten Durchsatzwerte Ihrer Tabelle jederzeit ändern, indem Sie die `DynamoDbClient’s` `updateTable` Methode aufrufen.

**Anmerkung**  
Wenn die benannte Tabelle für Ihr Konto und Ihre Region nicht existiert, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)wird a ausgelöst.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.UpdateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
```

 **Code** 

```
    public static void updateDynamoDBTable(DynamoDbClient ddb,
                                           String tableName,
                                           Long readCapacity,
                                           Long writeCapacity) {

        System.out.format(
                "Updating %s with new provisioned throughput values\n",
                tableName);
        System.out.format("Read capacity : %d\n", readCapacity);
        System.out.format("Write capacity : %d\n", writeCapacity);

        ProvisionedThroughput tableThroughput = ProvisionedThroughput.builder()
                .readCapacityUnits(readCapacity)
                .writeCapacityUnits(writeCapacity)
                .build();

        UpdateTableRequest request = UpdateTableRequest.builder()
                .provisionedThroughput(tableThroughput)
                .tableName(tableName)
                .build();

        try {
            ddb.updateTable(request);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }

        System.out.println("Done!");
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateTable.java) finden Sie unter GitHub.

## Löschen einer Tabelle
<a name="dynamodb-delete-table"></a>

Um eine Tabelle zu löschen, rufen Sie `DynamoDbClient’s` `deleteTable` method auf und geben Sie den Namen der Tabelle ein.

**Anmerkung**  
Wenn die benannte Tabelle für Ihr Konto und Ihre Region nicht existiert, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)wird a ausgelöst.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
```

 **Code** 

```
    public static void deleteDynamoDBTable(DynamoDbClient ddb, String tableName) {

        DeleteTableRequest request = DeleteTableRequest.builder()
                .tableName(tableName)
                .build();

        try {
            ddb.deleteTable(request);

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        System.out.println(tableName +" was successfully deleted!");
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteTable.java) finden Sie unter GitHub.

## Weitere Informationen
<a name="more-information"></a>
+  [Richtlinien für die Arbeit mit Tabellen finden](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html) Sie im Amazon DynamoDB Entwicklerhandbuch
+  [Arbeiten mit Tabellen finden Sie DynamoDB im](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html) Amazon DynamoDB Entwicklerhandbuch

# Arbeiten Sie mit Artikeln in DynamoDB
<a name="examples-dynamodb-items"></a>

*In DynamoDB ist ein Element eine Sammlung von *Attributen*, von denen jedes einen *Namen und einen Wert* hat.* Ein Attributwert kann eine Skalarfunktion, eine Gruppe oder ein Dokumenttyp sein. Weitere Informationen finden Sie unter [Benennungsregeln und Datentypen](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) im Amazon DynamoDB Entwicklerhandbuch.

## Abrufen (get) eines Elements aus einer Tabelle
<a name="dynamodb-get-item"></a>

Rufen Sie die DynamoDbClient `getItem` Methode auf und übergeben Sie ihr ein [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)Objekt mit dem Tabellennamen und dem Primärschlüsselwert des gewünschten Elements. Sie gibt ein [GetItemResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemResponse.html)Objekt mit allen Attributen für dieses Element zurück. Sie können einen oder mehrere [Projektionsausdrücke](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) in der `GetItemRequest` angeben, um spezifische Attribute abzurufen.

Sie können die `item()` Methode des zurückgegebenen `GetItemResponse` Objekts verwenden, um eine [Map](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) von Schlüssel- (String) - und Wertpaaren ([AttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html)) abzurufen, die dem Element zugeordnet sind.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
```

 **Code** 

```
    public static void getDynamoDBItem(DynamoDbClient ddb,String tableName,String key,String keyVal ) {

        HashMap<String,AttributeValue> keyToGet = new HashMap<String,AttributeValue>();

        keyToGet.put(key, AttributeValue.builder()
                .s(keyVal).build());

        GetItemRequest request = GetItemRequest.builder()
                .key(keyToGet)
                .tableName(tableName)
                .build();

        try {
            Map<String,AttributeValue> returnedItem = ddb.getItem(request).item();

            if (returnedItem != null) {
                Set<String> keys = returnedItem.keySet();
                System.out.println("Amazon DynamoDB table attributes: \n");

                for (String key1 : keys) {
                    System.out.format("%s: %s\n", key1, returnedItem.get(key1).toString());
                }
            } else {
                System.out.format("No item found with the key %s!\n", key);
            }
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/GetItem.java) finden Sie unter GitHub.

## Abrufen eines Elements aus einer Tabelle mithilfe des asynchronen Clients (get)
<a name="id1ddb"></a>

Rufen Sie die `getItem` Methode von auf DynamoDbAsyncClient und übergeben Sie ihr ein [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)Objekt mit dem Tabellennamen und dem Primärschlüsselwert des gewünschten Elements.

Sie können eine [Collection](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Collection.html)-Instance mit allen Attributen für dieses Element zurückgeben (siehe das folgende Beispiel).

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
```

 **Code** 

```
    public static void getItem(DynamoDbAsyncClient client, String tableName, String key,  String keyVal) {

        HashMap<String, AttributeValue> keyToGet =
                new HashMap<String, AttributeValue>();

        keyToGet.put(key, AttributeValue.builder()
                .s(keyVal).build());

        try {

            // Create a GetItemRequest instance
            GetItemRequest request = GetItemRequest.builder()
                    .key(keyToGet)
                    .tableName(tableName)
                    .build();

            // Invoke the DynamoDbAsyncClient object's getItem
            java.util.Collection<AttributeValue> returnedItem = client.getItem(request).join().item().values();

            // Convert Set to Map
            Map<String, AttributeValue> map = returnedItem.stream().collect(Collectors.toMap(AttributeValue::s, s->s));
            Set<String> keys = map.keySet();
            for (String sinKey : keys) {
                System.out.format("%s: %s\n", sinKey, map.get(sinKey).toString());
            }

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/DynamoDBAsyncGetItem.java) finden Sie unter. GitHub

## Hinzufügen eines neuen Elements in einer Tabelle
<a name="dynamodb-add-item"></a>

Erstellen Sie eine [Map](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) mit Schlüssel-Wert-Paaren, die die Attribute des Elements darstellen. Diese müssen Werte für die Primärschlüsselfelder der Tabelle enthalten. Wenn das Element mit dem Primärschlüssel bereits vorhanden ist, werden dessen Felder durch die Anforderung *aktualisiert*.

**Anmerkung**  
Wenn die benannte Tabelle für Ihr Konto und Ihre Region nicht existiert, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)wird a ausgelöst.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import java.util.HashMap;
```

 **Code** 

```
    public static void putItemInTable(DynamoDbClient ddb,
                                      String tableName,
                                      String key,
                                      String keyVal,
                                      String albumTitle,
                                      String albumTitleValue,
                                      String awards,
                                      String awardVal,
                                      String songTitle,
                                      String songTitleVal){

        HashMap<String,AttributeValue> itemValues = new HashMap<String,AttributeValue>();

        // Add all content to the table
        itemValues.put(key, AttributeValue.builder().s(keyVal).build());
        itemValues.put(songTitle, AttributeValue.builder().s(songTitleVal).build());
        itemValues.put(albumTitle, AttributeValue.builder().s(albumTitleValue).build());
        itemValues.put(awards, AttributeValue.builder().s(awardVal).build());

        PutItemRequest request = PutItemRequest.builder()
                .tableName(tableName)
                .item(itemValues)
                .build();

        try {
            ddb.putItem(request);
            System.out.println(tableName +" was successfully updated");

        } catch (ResourceNotFoundException e) {
            System.err.format("Error: The Amazon DynamoDB table \"%s\" can't be found.\n", tableName);
            System.err.println("Be sure that it exists and that you've typed its name correctly!");
            System.exit(1);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/PutItem.java) finden Sie unter GitHub.

## Aktualisieren eines vorhandenen Elements in einer Tabelle
<a name="dynamodb-update-item"></a>

Sie können ein Attribut für ein Element, das bereits in einer Tabelle vorhanden ist, aktualisieren, indem Sie die `updateItem`-Methode des DynamoDbClient aufrufen und einen Tabellennamen, Primärschlüsselwert und eine Zuordnung der Felder übergeben, die aktualisiert werden sollen.

**Anmerkung**  
Wenn die benannte Tabelle für Ihr Konto und Ihre Region nicht existiert oder wenn das Element, das durch den von Ihnen übergebenen Primärschlüssel identifiziert wurde, nicht existiert, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)wird a ausgelöst.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.AttributeAction;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import java.util.HashMap;
```

 **Code** 

```
    public static void updateTableItem(DynamoDbClient ddb,
                                       String tableName,
                                       String key,
                                       String keyVal,
                                       String name,
                                       String updateVal){

        HashMap<String,AttributeValue> itemKey = new HashMap<String,AttributeValue>();

        itemKey.put(key, AttributeValue.builder().s(keyVal).build());

        HashMap<String,AttributeValueUpdate> updatedValues =
                new HashMap<String,AttributeValueUpdate>();

        // Update the column specified by name with updatedVal
        updatedValues.put(name, AttributeValueUpdate.builder()
                .value(AttributeValue.builder().s(updateVal).build())
                .action(AttributeAction.PUT)
                .build());

        UpdateItemRequest request = UpdateItemRequest.builder()
                .tableName(tableName)
                .key(itemKey)
                .attributeUpdates(updatedValues)
                .build();

        try {
            ddb.updateItem(request);
        } catch (ResourceNotFoundException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }

        System.out.println("Done!");
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateItem.java) finden Sie unter GitHub.

## Löschen eines vorhandenen Elements aus einer Tabelle
<a name="dynamodb-delete-item"></a>

Sie können ein in einer Tabelle vorhandenes Element löschen, indem Sie die DynamoDbClient `deleteItem` Methode 'verwenden und einen Tabellennamen sowie den Primärschlüsselwert angeben.

**Anmerkung**  
Wenn die benannte Tabelle für Ihr Konto und Ihre Region nicht existiert oder wenn das Element, das durch den von Ihnen übergebenen Primärschlüssel identifiziert wurde, nicht existiert, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)wird a ausgelöst.

 **Importe** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import java.util.HashMap;
```

 **Code** 

```
  public static void deleteDynamoDBItem(DynamoDbClient ddb, String tableName, String key, String keyVal) {

        HashMap<String,AttributeValue> keyToGet =
                new HashMap<String,AttributeValue>();

        keyToGet.put(key, AttributeValue.builder()
                .s(keyVal)
                .build());

        DeleteItemRequest deleteReq = DeleteItemRequest.builder()
                .tableName(tableName)
                .key(keyToGet)
                .build();

        try {
            ddb.deleteItem(deleteReq);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Das [vollständige Beispiel](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteItem.java) finden Sie unter GitHub.

## Weitere Informationen
<a name="more-information"></a>
+  [Richtlinien für die Arbeit mit Elementen](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/best-practices.html) im Amazon DynamoDB Entwicklerhandbuch
+  [Arbeiten mit Elementen aus DynamoDB dem](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/WorkingWithItems.html) Amazon DynamoDB Entwicklerhandbuch

# Ordnen Sie Java-Objekte DynamoDB-Elementen zu mit dem AWS SDK for Java 2.x
<a name="dynamodb-enhanced-client"></a>

Die [DynamoDB Enhanced Client API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/package-summary.html) ist eine High-Level-Bibliothek, die der Nachfolger der `DynamoDBMapper` Klasse von im SDK for Java v1.x ist. Er bietet eine einfache Möglichkeit, clientseitige Klassen zu DynamoDB-Tabellen zuzuordnen. Sie definieren die Beziehungen zwischen Tabellen und ihren entsprechenden Datenklassen in Ihrem Code. Nach der Definition dieser Beziehungen können Sie verschiedene Operationen zum Erstellen, Lesen, Aktualisieren oder Löschen (Create, Read, Update, Delete, CRUD) für Tabellen oder Elemente in DynamoDB auf intuitive Weise ausführen.

Die DynamoDB Enhanced Client API umfasst auch die [Enhanced Document API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html), mit der Sie mit dokumentartigen Elementen arbeiten können, die keinem definierten Schema folgen. 

**Topics**
+ [Erste Schritte mit der DynamoDB Enhanced Client API](ddb-en-client-getting-started.md)
+ [Lernen Sie die Grundlagen der DynamoDB Enhanced Client API kennen](ddb-en-client-use.md)
+ [Verwenden Sie erweiterte Mapping-Funktionen](ddb-en-client-adv-features.md)
+ [Arbeiten Sie mit JSON-Dokumenten mit der Enhanced Document API für DynamoDB](ddb-en-client-doc-api.md)
+ [Verwenden Sie Erweiterungen, um DynamoDB Enhanced Client-Operationen anzupassen](ddb-en-client-extensions.md)
+ [Verwenden Sie die DynamoDB Enhanced Client API asynchron](ddb-en-client-async.md)
+ [Anmerkungen zu Datenklassen](ddb-en-client-anno-index.md)

# Erste Schritte mit der DynamoDB Enhanced Client API
<a name="ddb-en-client-getting-started"></a>

Das folgende Tutorial führt Sie in die Grundlagen ein, die Sie für die Arbeit mit der DynamoDB Enhanced Client API benötigen.

## Fügen Sie Abhängigkeiten hinzu
<a name="ddb-en-client-gs-dep"></a>

Um mit der Arbeit mit der DynamoDB Enhanced Client API in Ihrem Projekt zu beginnen, fügen Sie eine Abhängigkeit vom `dynamodb-enhanced` Maven-Artefakt hinzu. Dies wird in den folgenden Beispielen veranschaulicht. 

------
#### [ Maven ]

```
<project>
  <dependencyManagement>
   <dependencies>
      <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>bom</artifactId>
        <version><VERSION></version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
   </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>dynamodb-enhanced</artifactId>
    </dependency>
  </dependencies>
  ...
</project>
```

Suchen Sie im zentralen Maven-Repository nach der [neuesten Version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) und *<VERSION>* ersetzen Sie sie durch diesen Wert.

------
#### [ Gradle ]

```
repositories {
    mavenCentral()
}
dependencies {
    implementation(platform("software.amazon.awssdk:bom:<VERSION>"))
    implementation("software.amazon.awssdk:dynamodb-enhanced")
    ...
}
```

Suchen Sie im zentralen Maven-Repository nach der [neuesten Version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) und *<VERSION>* ersetzen Sie sie durch diesen Wert.

------

# Generieren Sie `TableSchema` aus einer Datenklasse eine
<a name="ddb-en-client-gs-tableschema"></a>

A `[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)` ermöglicht es dem erweiterten Client, DynamoDB-Attributwerte Ihren clientseitigen Klassen zuzuordnen. In diesem Tutorial erfahren Sie mehr über `TableSchema` s, die von einer statischen Datenklasse abgeleitet und mithilfe eines Builders aus Code generiert wurden.

## Verwenden Sie eine Datenklasse mit Anmerkungen
<a name="ddb-en-client-gs-tableschema-anno-bean"></a>

Das SDK for Java 2.x enthält eine [Reihe von Anmerkungen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html), die Sie mit einer Datenklasse verwenden können, um schnell eine `TableSchema` für die Zuordnung Ihrer Klassen zu Tabellen zu generieren.

[Erstellen Sie zunächst eine Datenklasse, die der Spezifikation entspricht. JavaBean ](https://download.oracle.com/otn-pub/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/beans.101.pdf) Die Spezifikation erfordert, dass eine Klasse einen öffentlichen Konstruktor ohne Argumente und Getter und Setter für jedes Attribut in der Klasse hat. Fügen Sie eine Anmerkung auf Klassenebene hinzu, um anzugeben, dass es sich bei der Datenklasse um eine handelt. `DynamoDbBean` Fügen Sie außerdem mindestens eine `DynamoDbPartitionKey` Anmerkung zum Getter- oder Setter-Wert für das Primärschlüsselattribut hinzu. 

Sie können [Anmerkungen auf Attributebene auf](ddb-en-client-anno-index.md) Getter oder Setter anwenden, aber nicht auf beide.

**Anmerkung**  
Der Begriff `property` wird normalerweise für einen Wert verwendet, der in a gekapselt ist. JavaBean In diesem Handbuch wird der Begriff jedoch `attribute` stattdessen verwendet, um mit der von DynamoDB verwendeten Terminologie konsistent zu sein.

Die folgende `Customer` Klasse zeigt Anmerkungen, die die Klassendefinition mit einer DynamoDB-Tabelle verknüpfen.

### `Customer`-Klasse
<a name="ddb-en-client-gs-tableschema-anno-bean-cust"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.time.Instant;

@DynamoDbBean
public class Customer {

    private String id;
    private String name;
    private String email;
    private Instant regDate;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }

    public void setId(String id) { this.id = id; }

    public String getCustName() { return this.name; }

    public void setCustName(String name) { this.name = name; }

    @DynamoDbSortKey
    public String getEmail() { return this.email; }

    public void setEmail(String email) { this.email = email; }

    public Instant getRegistrationDate() { return this.regDate; }

    public void setRegistrationDate(Instant registrationDate) { this.regDate = registrationDate; }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", email=" + email
                + ", regDate=" + regDate + "]";
    }
}
```

Nachdem Sie eine annotierte Datenklasse erstellt haben, verwenden Sie sie, um die zu erstellen`TableSchema`, wie im folgenden Codeausschnitt gezeigt.

```
static final TableSchema<Customer> customerTableSchema = TableSchema.fromBean(Customer.class);
```

A `TableSchema` ist so konzipiert, dass es statisch und unveränderlich ist. Sie können es normalerweise beim Laden der Klasse instanziieren.

Die statische `TableSchema.fromBean()` Factory-Methode untersucht die Bean, um die Zuordnung von Datenklassenattributen (Eigenschaften) zu und von DynamoDB-Attributen zu generieren.

Ein Beispiel für die Arbeit mit einem Datenmodell, das aus mehreren Datenklassen besteht, finden Sie in der `Person` Klasse im Abschnitt. [Arbeiten Sie mit Attributen wie Beans, Maps, Listen und Sets](ddb-en-client-adv-features-nested.md)

## Verwenden Sie einen Builder
<a name="ddb-en-client-gs-tableschema-builder"></a>

Sie können die Kosten für die Bean-Introspektion überspringen, wenn Sie das Tabellenschema im Code definieren. Wenn Sie das Schema codieren, muss Ihre Klasse weder den JavaBean Benennungsstandards entsprechen noch muss sie mit Anmerkungen versehen werden. Das folgende Beispiel verwendet einen Builder und entspricht dem `Customer` Klassenbeispiel, das Anmerkungen verwendet.

```
static final TableSchema<Customer> customerTableSchema =
                TableSchema.builder(Customer.class)
                        .newItemSupplier(Customer::new)
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(Customer::getId)
                                .setter(Customer::setId)
                                .tags(StaticAttributeTags.primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("email")
                                .getter(Customer::getEmail)
                                .setter(Customer::setEmail)
                                .tags(StaticAttributeTags.primarySortKey()))
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(Customer::getCustName)
                                .setter(Customer::setCustName))
                        .addAttribute(Instant.class, a -> a.name("registrationDate")
                                .getter(Customer::getRegistrationDate)
                                .setter(Customer::setRegistrationDate))
                        .build();
```

# Erstellen Sie einen erweiterten Client und `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable"></a>

## Erstellen Sie einen erweiterten Client
<a name="ddb-en-client-getting-started-dynamodbTable-eclient"></a>

Die [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)Klasse oder ihr asynchrones Gegenstück, [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html), ist der Einstiegspunkt für die Arbeit mit der DynamoDB Enhanced Client API.

Der erweiterte Client benötigt einen Standard, um die Arbeit ausführen `[DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)` zu können. Die API bietet zwei Möglichkeiten, eine `DynamoDbEnhancedClient` Instanz zu erstellen. Die erste Option, die im folgenden Ausschnitt gezeigt wird, erstellt einen Standard `DynamoDbClient` mit Standardeinstellungen, die aus den Konfigurationseinstellungen übernommen wurden.

```
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create();
```

Wenn Sie den zugrunde liegenden Standardclient konfigurieren möchten, können Sie ihn der Builder-Methode des erweiterten Clients zur Verfügung stellen, wie im folgenden Codeausschnitt gezeigt.

```
// Configure an instance of the standard DynamoDbClient.
DynamoDbClient standardClient = DynamoDbClient.builder()
    .region(Region.US_EAST_1)
    .credentialsProvider(ProfileCredentialsProvider.create())
    .build();

// Use the configured standard client with the enhanced client.
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
    .dynamoDbClient(standardClient)
    .build();
```

## Erstellen einer `DynamoDbTable`-Instance
<a name="ddb-en-client-getting-started-dynamodbTable-table"></a>

Stellen Sie sich a [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)als die clientseitige Darstellung einer DynamoDB-Tabelle vor, die die von a bereitgestellte Zuordnungsfunktion verwendet. `TableSchema` Die `DynamoDbTable` Klasse stellt Methoden für CRUD-Operationen bereit, mit denen Sie mit einer einzelnen DynamoDB-Tabelle interagieren können.

`DynamoDbTable<T>`ist eine generische Klasse, die ein einzelnes Typargument akzeptiert, unabhängig davon, ob es sich um eine benutzerdefinierte Klasse handelt oder um eine, `EnhancedDocument` wenn mit dokumentartigen Elementen gearbeitet wird. Dieser Argumenttyp stellt die Beziehung zwischen der Klasse, die Sie verwenden, und der einzelnen DynamoDB-Tabelle her.

Verwenden Sie die `table()` Factory-Methode von`DynamoDbEnhancedClient`, um eine `DynamoDbTable` Instanz zu erstellen, wie im folgenden Codeausschnitt gezeigt.

```
static final DynamoDbTable<Customer> customerTable = 
        enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

`DynamoDbTable`Instanzen sind Kandidaten für Singletons, da sie unveränderlich sind und in Ihrer gesamten Anwendung verwendet werden können.

Ihr Code hat jetzt eine speicherinterne Darstellung einer DynamoDB-Tabelle, die mit Instanzen arbeiten kann. `Customer` Die tatsächliche DynamoDB-Tabelle ist möglicherweise vorhanden oder nicht. Wenn die angegebene Tabelle `Customer` bereits existiert, können Sie damit beginnen, CRUD-Operationen an ihr durchzuführen. Wenn sie nicht existiert, verwenden Sie die `DynamoDbTable` Instanz, um die Tabelle zu erstellen, wie im nächsten Abschnitt beschrieben.

# Erstellen Sie bei Bedarf eine DynamoDB-Tabelle
<a name="ddb-en-client-gs-ddbtable"></a>

Nachdem Sie eine `DynamoDbTable` Instanz erstellt haben, verwenden Sie sie, um eine *einmalige* Erstellung einer Tabelle in DynamoDB durchzuführen.

## Beispielcode für Tabelle erstellen
<a name="ddb-en-client-gs-ddbtable-createex"></a>

Im folgenden Beispiel wird eine DynamoDB-Tabelle erstellt, die auf der `Customer` Datenklasse basiert. 

In diesem Beispiel wird eine DynamoDB-Tabelle mit dem Namen erstellt, der mit dem Klassennamen `Customer` identisch ist, aber der Tabellenname kann auch ein anderer sein. Wie auch immer Sie die Tabelle benennen, Sie müssen diesen Namen in weiteren Anwendungen verwenden, um mit der Tabelle arbeiten zu können. Geben Sie der `table()` Methode diesen Namen jedes Mal, wenn Sie ein anderes `DynamoDbTable` Objekt erstellen, um mit der zugrunde liegenden DynamoDB-Tabelle zu arbeiten.

Mit dem an die `createTable` Methode übergebenen Java-Lambda-Parameter können Sie die Tabelle [anpassen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html). `builder` In diesem Beispiel wird der [bereitgestellte Durchsatz konfiguriert](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual). Wenn Sie beim Erstellen einer Tabelle die Standardeinstellungen verwenden möchten, überspringen Sie den Builder, wie im folgenden Codeausschnitt gezeigt.

```
customerTable.createTable();
```

Wenn Standardeinstellungen verwendet werden, werden keine Werte für den bereitgestellten Durchsatz festgelegt. Stattdessen ist der Abrechnungsmodus für die Tabelle auf [On-Demand-Modus](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand) eingestellt.

In dem Beispiel wird auch ein verwendet, `[DynamoDbWaiter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/waiters/DynamoDbWaiter.html)` bevor versucht wird, den in der Antwort erhaltenen Tabellennamen auszudrucken. Die Erstellung einer Tabelle dauert einige Zeit. Wenn Sie also einen Kellner verwenden, müssen Sie keine Logik schreiben, die den DynamoDB-Dienst abfragt, um festzustellen, ob die Tabelle existiert, bevor Sie die Tabelle verwenden.

### Importe
<a name="ddb-en-client-gs-ddbtable-imports"></a>

```
import com.example.dynamodb.Customer;
import software.amazon.awssdk.core.internal.waiters.ResponseOrException;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
```

### Code
<a name="ddb-en-client-gs-ddbtable-code"></a>

```
 public static void createCustomerTable(DynamoDbTable<Customer> customerTable, DynamoDbClient standardClient) {
     // Create the DynamoDB table using the 'customerTable' DynamoDbTable instance.
     customerTable.createTable(builder -> builder
             .provisionedThroughput(b -> b
                     .readCapacityUnits(10L)
                     .writeCapacityUnits(10L)
                     .build())
     );
     // The DynamoDbClient instance (named 'standardClient') passed to the builder for the DynamoDbWaiter is the same instance
     // that was passed to the builder of the DynamoDbEnhancedClient instance that we created previously.
     // By using the same instance, it ensures that the same Region that was configured on the standard DynamoDbClient 
     // instance is used for other service clients that accept a DynamoDbClient during construction.
     try (DynamoDbWaiter waiter = DynamoDbWaiter.builder().client(standardClient).build()) { // DynamoDbWaiter is Autocloseable
         ResponseOrException<DescribeTableResponse> response = waiter
                 .waitUntilTableExists(builder -> builder.tableName("Customer").build())
                 .matched();
         DescribeTableResponse tableDescription = response.response().orElseThrow(
                 () -> new RuntimeException("Customer table was not created."));
         // The actual error can be inspected in response.exception()
         logger.info("Customer table was created.");
     }
 }
```

**Anmerkung**  
Die Attributnamen einer DynamoDB-Tabelle beginnen mit einem Kleinbuchstaben, wenn die Tabelle aus einer Datenklasse generiert wird. Wenn der Attributname der Tabelle mit einem Großbuchstaben beginnen soll, verwenden Sie die [`@DynamoDbAttribute(NAME)`Anmerkung](ddb-en-client-adv-features-inex-attr.md) und geben Sie den gewünschten Namen als Parameter an.

# Führen Sie Operationen aus
<a name="ddb-en-client-gs-use"></a>

Nachdem die Tabelle erstellt wurde, verwenden Sie die `DynamoDbTable` Instanz, um Operationen mit der DynamoDB-Tabelle durchzuführen. 

Im folgenden Beispiel `DynamoDbTable<Customer>` wird ein Singleton als Parameter zusammen mit einer [`Customer`Datenklasseninstanz](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) übergeben, um der Tabelle ein neues Element hinzuzufügen.

```
    public static void putItemExample(DynamoDbTable<Customer> customerTable, Customer customer){
        logger.info(customer.toString());
        customerTable.putItem(customer);
    }
```

## `Customer`-Objekt
<a name="perform_ops_create_customer_instatnce"></a>

```
        Customer customer = new Customer();
        customer.setId("1");
        customer.setCustName("Customer Name");
        customer.setEmail("customer@example.com");
        customer.setRegistrationDate(Instant.parse("2023-07-03T10:15:30.00Z"));
```

Bevor Sie das `customer` Objekt an den DynamoDB-Dienst senden, protokollieren Sie die Ausgabe der `toString()` Methode des Objekts, um sie mit dem zu vergleichen, was der erweiterte Client sendet.

```
Customer [id=1, name=Customer Name, email=customer@example.com, regDate=2023-07-03T10:15:30Z]
```

Die Protokollierung auf Wireebene zeigt die Nutzlast der generierten Anfrage. Der erweiterte Client generierte die Low-Level-Darstellung anhand der Datenklasse. Das `regDate` Attribut, ein `Instant` Typ in Java, wird als DynamoDB-Zeichenfolge dargestellt.

```
{
  "TableName": "Customer",
  "Item": {
    "registrationDate": {
      "S": "2023-07-03T10:15:30Z"
    },
    "id": {
      "S": "1"
    },
    "custName": {
      "S": "Customer Name"
    },
    "email": {
      "S": "customer@example.com"
    }
  }
}
```

# Arbeiten Sie mit einer vorhandenen Tabelle
<a name="ddb-en-client-gs-existingtable"></a>

Im vorherigen Abschnitt wurde gezeigt, wie eine DynamoDB-Tabelle erstellt wird, die mit einer Java-Datenklasse beginnt. Wenn Sie bereits über eine bestehende Tabelle verfügen und die Funktionen des erweiterten Clients nutzen möchten, können Sie eine Java-Datenklasse erstellen, die mit der Tabelle arbeitet. Sie müssen die DynamoDB-Tabelle untersuchen und der Datenklasse die erforderlichen Anmerkungen hinzufügen. 

Rufen Sie die Methode auf, bevor Sie mit einer vorhandenen Tabelle arbeiten. `DynamoDbEnhanced.table()` Dies wurde im vorherigen Beispiel mit der folgenden Anweisung durchgeführt.

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

Nachdem die `DynamoDbTable` Instanz zurückgegeben wurde, können Sie sofort mit der Arbeit an der zugrunde liegenden Tabelle beginnen. Sie müssen die Tabelle nicht neu erstellen, indem Sie die `DynamoDbTable.createTable()` Methode aufrufen.

Das folgende Beispiel veranschaulicht dies, indem sofort eine `Customer` Instanz aus der DynamoDB-Tabelle abgerufen wird.

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
// The Customer table exists already and has an item with a primary key value of "1" and a sort key value of "customer@example.com".
customerTable.getItem(
        Key.builder().
                partitionValue("1").
                sortValue("customer@example.com").build());
```

**Wichtig**  
Der in der `table()` Methode verwendete Tabellenname muss mit dem vorhandenen DynamoDB-Tabellennamen übereinstimmen.

# Lernen Sie die Grundlagen der DynamoDB Enhanced Client API kennen
<a name="ddb-en-client-use"></a>

In diesem Thema werden die grundlegenden Funktionen der DynamoDB Enhanced Client API beschrieben und sie mit der [standardmäßigen DynamoDB-Client-API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html) verglichen.

Wenn Sie mit der DynamoDB Enhanced Client API noch nicht vertraut sind, empfehlen wir Ihnen, das [Einführungstutorial](ddb-en-client-getting-started.md) zu lesen, um sich mit den grundlegenden Klassen vertraut zu machen.

## DynamoDB-Elemente in Java
<a name="ddb-en-client-use-usecase"></a>

DynamoDB-Tabellen speichern Elemente. Abhängig von Ihrem Anwendungsfall können Elemente auf der Java-Seite die Form von statisch strukturierten Daten oder dynamisch erstellten Strukturen annehmen. 

Wenn Ihr Anwendungsfall Elemente mit einem konsistenten Satz von Attributen erfordert, verwenden Sie [annotierte Klassen](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean) oder verwenden Sie einen [Builder](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-builder), um die entsprechenden statisch typisierten Elemente zu generieren. `TableSchema` 

Wenn Sie Elemente speichern müssen, die aus unterschiedlichen Strukturen bestehen, können Sie alternativ eine erstellen. `DocumentTableSchema` `DocumentTableSchema`ist Teil der [Enhanced Document API](ddb-en-client-doc-api.md) und benötigt nur einen statisch typisierten Primärschlüssel und funktioniert mit `EnhancedDocument` Instanzen, die die Datenelemente enthalten. [Die Enhanced Document API wird in einem anderen Thema behandelt.](ddb-en-client-doc-api.md)

## Attributtypen für Datenmodellklassen
<a name="ddb-en-client-use-types"></a>

Obwohl DynamoDB im Vergleich zum Rich-Type-System [von Java eine geringe Anzahl von Attributtypen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) unterstützt, bietet die DynamoDB Enhanced Client API Mechanismen zum Konvertieren von Mitgliedern einer Java-Klasse in und aus DynamoDB-Attributtypen.

Bei den Attributtypen (Eigenschaften) Ihrer Java-Datenklassen sollte es sich um Objekttypen und nicht um Primitive handeln. Verwenden Sie beispielsweise immer Datentypen `Long` und `Integer` Objekte, nicht `long` `int` Primitive.

[Standardmäßig unterstützt die DynamoDB Enhanced Client-API Attributkonverter für eine Vielzahl von Typen, wie [Integer [BigDecimal](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/BigDecimalAttributeConverter.html)](https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html), [String](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html) und Instant.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/InstantAsStringAttributeConverter.html) Die Liste wird in den [bekannten Implementierungsklassen der AttributeConverter Schnittstelle](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html) angezeigt. Die Liste enthält viele Typen und Sammlungen wie Karten, Listen und Sets.

Um die Daten für einen Attributtyp zu speichern, der standardmäßig nicht unterstützt wird oder nicht der JavaBean Konvention entspricht, können Sie eine benutzerdefinierte `AttributeConverter` Implementierung für die Konvertierung schreiben. Ein [Beispiel](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-example) finden Sie im Abschnitt zur Attributkonvertierung.

Um die Daten für einen Attributtyp zu speichern, dessen Klasse der Java-Beans-Spezifikation (oder einer [unveränderlichen Datenklasse](ddb-en-client-use-immut.md)) entspricht, können Sie zwei Ansätze wählen. 
+ Wenn Sie Zugriff auf die Quelldatei haben, können Sie die Klasse mit `@DynamoDbBean` (oder) annotieren. `@DynamoDbImmutable` Der Abschnitt, der verschachtelte Attribute behandelt, zeigt [Beispiele für](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-anno) die Verwendung von Klassen mit Anmerkungen.
+ Wenn Sie keinen Zugriff auf die Quelldatei der JavaBean Datenklasse für das Attribut haben (oder Sie die Quelldatei einer Klasse, auf die Sie Zugriff haben, nicht mit Anmerkungen versehen möchten), können Sie den Builder-Ansatz verwenden. Dadurch wird ein Tabellenschema erstellt, ohne die Schlüssel zu definieren. Anschließend können Sie dieses Tabellenschema in einem anderen Tabellenschema verschachteln, um die Zuordnung durchzuführen. Der Abschnitt mit verschachtelten Attributen enthält ein [Beispiel](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-builder), das die Verwendung verschachtelter Schemas zeigt.

### Null-Werte
<a name="ddb-en-client-use-types-nulls"></a>

Wenn Sie die `putItem` Methode verwenden, nimmt der erweiterte Client keine nullwertigen Attribute eines zugewiesenen Datenobjekts in die Anforderung an DynamoDB auf.

Das Standardverhalten des SDK für `updateItem` Anfragen entfernt Attribute aus dem Element in DynamoDB, die in dem Objekt, das Sie in der Methode einreichen, auf Null gesetzt sind. `updateItem` Wenn Sie beabsichtigen, einige Attributwerte zu aktualisieren und die anderen unverändert zu lassen, haben Sie zwei Möglichkeiten.
+ Rufen Sie das Element (mithilfe von`getItem`) ab, bevor Sie Änderungen an den Werten vornehmen. Mit diesem Ansatz übermittelt das SDK alle aktualisierten und alten Werte an DynamoDB.
+ Verwenden Sie entweder `[IgnoreNullsMode](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html).SCALAR_ONLY` oder, `IgnoreNullsMode.MAPS_ONLY` wenn Sie die Anfrage erstellen, um das Element zu aktualisieren. Beide Modi ignorieren nullwertige Eigenschaften im Objekt, die skalare Attribute in DynamoDB darstellen. Das [Aktualisieren Sie Elemente, die komplexe Typen enthalten](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-updates) Thema in diesem Handbuch enthält weitere Informationen zu den `IgnoreNullsMode` Werten und zur Arbeit mit komplexen Typen.

Das folgende `ignoreNullsMode()` Beispiel zeigt die `updateItem()` Methode.

```
    public static void updateItemNullsExample() {
        Customer customer = new Customer();
        customer.setCustName("CustomerName");
        customer.setEmail("email");
        customer.setId("1");
        customer.setRegistrationDate(Instant.now());

        logger.info("Original customer: {}", customer);

        // Put item with values for all attributes.
        try {
            customerAsyncDynamoDbTable.putItem(customer).join();
        } catch (RuntimeException rte) {
            logger.error("A exception occurred during putItem: {}", rte.getCause().getMessage(), rte);
            return;
        }

        // Create a Customer instance with the same 'id' and 'email' values, but a different 'name' value.
        // Do not set the 'registrationDate' attribute.
        Customer customerForUpdate = new Customer();
        customerForUpdate.setCustName("NewName");
        customerForUpdate.setEmail("email");
        customerForUpdate.setId("1");

        // Update item without setting the 'registrationDate' property and set IgnoreNullsMode to SCALAR_ONLY.
        try {
            Customer updatedWithNullsIgnored = customerAsyncDynamoDbTable.updateItem(b -> b
                            .item(customerForUpdate)
                            .ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY))
                    .join();
            logger.info("Customer updated with nulls ignored: {}", updatedWithNullsIgnored.toString());
        } catch (RuntimeException rte) {
            logger.error("An exception occurred during updateItem: {}", rte.getCause().getMessage(), rte);
            return;
        }

        // Update item without setting the registrationDate attribute and not setting ignoreNulls to true.
        try {
            Customer updatedWithNullsUsed = customerAsyncDynamoDbTable.updateItem(customerForUpdate)
                    .join();
            logger.info("Customer updated with nulls used: {}", updatedWithNullsUsed.toString());
        } catch (RuntimeException rte) {
            logger.error("An exception occurred during updateItem: {}", rte.getCause().getMessage(), rte);
        }
    }


// Logged lines. 
Original customer: Customer [id=1, name=CustomerName, email=email, regDate=2024-10-11T14:12:30.222858Z]
Customer updated with nulls ignored: Customer [id=1, name=NewName, email=email, regDate=2024-10-11T14:12:30.222858Z]
Customer updated with nulls used: Customer [id=1, name=NewName, email=email, regDate=null]
```

## Grundlegende Methoden des DynamoDB Enhanced Client
<a name="ddb-en-client-use-basic-ops"></a>

Die grundlegenden Methoden des erweiterten Clients sind den DynamoDB-Dienstoperationen zugeordnet, nach denen sie benannt sind. Die folgenden Beispiele zeigen die einfachste Variante der einzelnen Methoden. Sie können jede Methode anpassen, indem Sie ein erweitertes Anforderungsobjekt übergeben. Verbesserte Anforderungsobjekte bieten die meisten Funktionen, die im Standard-DynamoDB-Client verfügbar sind. Sie sind in der AWS SDK for Java 2.x API-Referenz vollständig dokumentiert.

Das Beispiel verwendet das zuvor [`Customer`-Klasse](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) Gezeigte.

```
// CreateTable
customerTable.createTable();

// GetItem
Customer customer = customerTable.getItem(Key.builder().partitionValue("a123").build());

// UpdateItem
Customer updatedCustomer = customerTable.updateItem(customer);

// PutItem
customerTable.putItem(customer);

// DeleteItem
Customer deletedCustomer = customerTable.deleteItem(Key.builder().partitionValue("a123").sortValue(456).build());

// Query
PageIterable<Customer> customers = customerTable.query(keyEqualTo(k -> k.partitionValue("a123")));

// Scan
PageIterable<Customer> customers = customerTable.scan();

// BatchGetItem
BatchGetResultPageIterable batchResults = 
    enhancedClient.batchGetItem(r -> r.addReadBatch(ReadBatch.builder(Customer.class)
                                      .mappedTableResource(customerTable)
                                      .addGetItem(key1)
                                      .addGetItem(key2)
                                      .addGetItem(key3)
                                      .build()));

// BatchWriteItem
batchResults = enhancedClient.batchWriteItem(r -> r.addWriteBatch(WriteBatch.builder(Customer.class)
                                                   .mappedTableResource(customerTable)
                                                   .addPutItem(customer)
                                                   .addDeleteItem(key1)
                                                   .addDeleteItem(key1)
                                                   .build()));

// TransactGetItems
transactResults = enhancedClient.transactGetItems(r -> r.addGetItem(customerTable, key1)
                                                        .addGetItem(customerTable, key2));

// TransactWriteItems
enhancedClient.transactWriteItems(r -> r.addConditionCheck(customerTable, 
                                                           i -> i.key(orderKey)
                                                                 .conditionExpression(conditionExpression))
                                        .addUpdateItem(customerTable, customer)
                                        .addDeleteItem(customerTable, key));
```

## DynamoDB Enhanced Client mit dem Standard-DynamoDB-Client vergleichen
<a name="ddb-en-client-use-compare"></a>

Sowohl der [standardmäßige](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html) als auch der [erweiterte](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/package-summary.html) DynamoDB-Client APIs ermöglichen es Ihnen, mit DynamoDB-Tabellen zu arbeiten, um CRUD-Operationen (Create, Read, Update and Delete) auf Datenebene durchzuführen. Der Unterschied zwischen den Clients besteht darin, wie dies erreicht wird. APIs Mit dem Standard-Client arbeiten Sie direkt mit Datenattributen auf niedriger Ebene. Die erweiterte Client-API verwendet vertraute Java-Klassen und ist der Low-Level-API im Hintergrund zugeordnet.

Während beide Clients Operationen auf Datenebene APIs unterstützen, unterstützt der standardmäßige DynamoDB-Client auch Operationen auf Ressourcenebene. Operationen auf Ressourcenebene verwalten die Datenbank, z. B. das Erstellen von Backups, das Auflisten von Tabellen und das Aktualisieren von Tabellen. Die erweiterte Client-API unterstützt eine bestimmte Anzahl von Vorgängen auf Ressourcenebene, z. B. das Erstellen, Beschreiben und Löschen von Tabellen.

Um die unterschiedlichen Ansätze der beiden Clients zu veranschaulichen APIs, zeigen die folgenden Codebeispiele die Erstellung derselben `ProductCatalog` Tabelle mit dem Standard-Client und dem erweiterten Client.

### Vergleichen: Erstellen Sie eine Tabelle mit dem standardmäßigen DynamoDB-Client
<a name="ddb-en-client-use-compare-cs1"></a>

```
DependencyFactory.dynamoDbClient().createTable(builder -> builder
        .tableName(TABLE_NAME)
        .attributeDefinitions(
                b -> b.attributeName("id").attributeType(ScalarAttributeType.N),
                b -> b.attributeName("title").attributeType(ScalarAttributeType.S),
                b -> b.attributeName("isbn").attributeType(ScalarAttributeType.S)
        )
        .keySchema(
                builder1 -> builder1.attributeName("id").keyType(KeyType.HASH),
                builder2 -> builder2.attributeName("title").keyType(KeyType.RANGE)
        )
        .globalSecondaryIndexes(builder3 -> builder3
                        .indexName("products_by_isbn")
                        .keySchema(builder2 -> builder2
                                .attributeName("isbn").keyType(KeyType.HASH))
                        .projection(builder2 -> builder2
                                .projectionType(ProjectionType.INCLUDE)
                                .nonKeyAttributes("price", "authors"))
                        .provisionedThroughput(builder4 -> builder4
                                .writeCapacityUnits(5L).readCapacityUnits(5L))
        )
        .provisionedThroughput(builder1 -> builder1
                .readCapacityUnits(5L).writeCapacityUnits(5L))
);
```

### Vergleichen: Erstellen Sie eine Tabelle mit dem DynamoDB Enhanced Client
<a name="ddb-en-client-use-compare-cs2"></a>

```
DynamoDbEnhancedClient enhancedClient = DependencyFactory.enhancedClient();
productCatalog = enhancedClient.table(TABLE_NAME, TableSchema.fromImmutableClass(ProductCatalog.class));
productCatalog.createTable(b -> b
        .provisionedThroughput(b1 -> b1.readCapacityUnits(5L).writeCapacityUnits(5L))
        .globalSecondaryIndices(b2 -> b2.indexName("products_by_isbn")
                .projection(b4 -> b4
                        .projectionType(ProjectionType.INCLUDE)
                        .nonKeyAttributes("price", "authors"))
                .provisionedThroughput(b3 -> b3.writeCapacityUnits(5L).readCapacityUnits(5L))
        )
);
```

Der erweiterte Client verwendet die folgende Datenklasse mit Anmerkungen. Der DynamoDB Enhanced Client ordnet Java-Datentypen DynamoDB-Datentypen zu und sorgt so für weniger ausführlichen Code, der leichter nachzuvollziehen ist. `ProductCatalog`ist ein Beispiel für die Verwendung einer unveränderlichen Klasse mit dem DynamoDB Enhanced Client. Die Verwendung unveränderlicher Klassen für zugeordnete Datenklassen wird später in diesem [Thema erörtert](ddb-en-client-use-immut.md).

### `ProductCatalog`-Klasse
<a name="ddb-en-client-use-compare-cs3"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbIgnore;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.math.BigDecimal;
import java.util.Objects;
import java.util.Set;

@DynamoDbImmutable(builder = ProductCatalog.Builder.class)
public class ProductCatalog implements Comparable<ProductCatalog> {
    private Integer id;
    private String title;
    private String isbn;
    private Set<String> authors;
    private BigDecimal price;


    private ProductCatalog(Builder builder){
        this.authors = builder.authors;
        this.id = builder.id;
        this.isbn = builder.isbn;
        this.price = builder.price;
        this.title = builder.title;
    }

    public static Builder builder(){ return new Builder(); }

    @DynamoDbPartitionKey
    public Integer id() { return id; }
    
    @DynamoDbSortKey
    public String title() { return title; }
    
    @DynamoDbSecondaryPartitionKey(indexNames = "products_by_isbn")
    public String isbn() { return isbn; }
    public Set<String> authors() { return authors; }
    public BigDecimal price() { return price; }


    public static final class Builder {
      private Integer id;
      private String title;
      private String isbn;
      private Set<String> authors;
      private BigDecimal price;
      private Builder(){}

      public Builder id(Integer id) { this.id = id; return this; }
      public Builder title(String title) { this.title = title; return this; }
      public Builder isbn(String ISBN) { this.isbn = ISBN; return this; }
      public Builder authors(Set<String> authors) { this.authors = authors; return this; }
      public Builder price(BigDecimal price) { this.price = price; return this; }
      public ProductCatalog build() { return new ProductCatalog(this); }
  }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("ProductCatalog{");
        sb.append("id=").append(id);
        sb.append(", title='").append(title).append('\'');
        sb.append(", isbn='").append(isbn).append('\'');
        sb.append(", authors=").append(authors);
        sb.append(", price=").append(price);
        sb.append('}');
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ProductCatalog that = (ProductCatalog) o;
        return id.equals(that.id) && title.equals(that.title) && Objects.equals(isbn, that.isbn) && Objects.equals(authors, that.authors) && Objects.equals(price, that.price);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, title, isbn, authors, price);
    }

    @Override
    @DynamoDbIgnore
    public int compareTo(ProductCatalog other) {
        if (this.id.compareTo(other.id) != 0){
            return this.id.compareTo(other.id);
        } else {
            return this.title.compareTo(other.title);
        }
    }
}
```

Die folgenden beiden Codebeispiele für Batch-Schreibvorgänge veranschaulichen die Ausführlichkeit und die mangelnde Typsicherheit bei der Verwendung des Standardclients im Gegensatz zum erweiterten Client.

### Vergleich: Batch-Schreiben mit dem standardmäßigen DynamoDB-Client
<a name="ddb-en-client-use-compare-cs4"></a>

```
    public static void batchWriteStandard(DynamoDbClient dynamoDbClient, String tableName) {

        Map<String, AttributeValue> catalogItem = Map.of(
                "authors", AttributeValue.builder().ss("a", "b").build(),
                "id", AttributeValue.builder().n("1").build(),
                "isbn", AttributeValue.builder().s("1-565-85698").build(),
                "title", AttributeValue.builder().s("Title 1").build(),
                "price", AttributeValue.builder().n("52.13").build());

        Map<String, AttributeValue> catalogItem2 = Map.of(
                "authors", AttributeValue.builder().ss("a", "b", "c").build(),
                "id", AttributeValue.builder().n("2").build(),
                "isbn", AttributeValue.builder().s("1-208-98073").build(),
                "title", AttributeValue.builder().s("Title 2").build(),
                "price", AttributeValue.builder().n("21.99").build());

        Map<String, AttributeValue> catalogItem3 = Map.of(
                "authors", AttributeValue.builder().ss("g", "k", "c").build(),
                "id", AttributeValue.builder().n("3").build(),
                "isbn", AttributeValue.builder().s("7-236-98618").build(),
                "title", AttributeValue.builder().s("Title 3").build(),
                "price", AttributeValue.builder().n("42.00").build());

        Set<WriteRequest> writeRequests = Set.of(
                WriteRequest.builder().putRequest(b -> b.item(catalogItem)).build(),
                WriteRequest.builder().putRequest(b -> b.item(catalogItem2)).build(),
                WriteRequest.builder().putRequest(b -> b.item(catalogItem3)).build());

        Map<String, Set<WriteRequest>> productCatalogItems = Map.of(
                "ProductCatalog", writeRequests);

        BatchWriteItemResponse response = dynamoDbClient.batchWriteItem(b -> b.requestItems(productCatalogItems));

        logger.info("Unprocessed items: " + response.unprocessedItems().size());
    }
```

### Vergleich: Batch-Schreiben mit dem DynamoDB Enhanced Client
<a name="ddb-en-client-use-compare-cs5"></a>

```
    public static void batchWriteEnhanced(DynamoDbTable<ProductCatalog> productCatalog) {
        ProductCatalog prod = ProductCatalog.builder()
                .id(1)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(52.13))
                .title("Title 1")
                .build();
        ProductCatalog prod2 = ProductCatalog.builder()
                .id(2)
                .isbn("1-208-98073")
                .authors(new HashSet<>(Arrays.asList("a", "b", "c")))
                .price(BigDecimal.valueOf(21.99))
                .title("Title 2")
                .build();
        ProductCatalog prod3 = ProductCatalog.builder()
                .id(3)
                .isbn("7-236-98618")
                .authors(new HashSet<>(Arrays.asList("g", "k", "c")))
                .price(BigDecimal.valueOf(42.00))
                .title("Title 3")
                .build();

        BatchWriteResult batchWriteResult = DependencyFactory.enhancedClient()
                .batchWriteItem(b -> b.writeBatches(
                        WriteBatch.builder(ProductCatalog.class)
                                .mappedTableResource(productCatalog)
                                .addPutItem(prod).addPutItem(prod2).addPutItem(prod3)
                                .build()
                ));
        logger.info("Unprocessed items: " + batchWriteResult.unprocessedPutItemsForTable(productCatalog).size());
    }
```

# Arbeiten Sie mit unveränderlichen Datenklassen
<a name="ddb-en-client-use-immut"></a>

Die Mapping-Funktion der DynamoDB Enhanced Client API funktioniert mit unveränderlichen Datenklassen. Eine unveränderliche Klasse hat nur Getter und erfordert eine Builder-Klasse, die das SDK verwendet, um Instances der Klasse zu erstellen. Anstatt die `@DynamoDbBean` Annotation zu verwenden, wie in der [Customer-Klasse](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) gezeigt, verwenden unveränderliche Klassen die `@DynamoDbImmutable` Annotation, die einen Parameter verwendet, der angibt, welche Builder-Klasse verwendet werden soll.

Die folgende Klasse ist eine unveränderliche Version von. `Customer`

```
package org.example.tests.model.immutable;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.time.Instant;

@DynamoDbImmutable(builder = CustomerImmutable.Builder.class)
public class CustomerImmutable {
    private final String id;
    private final String name;
    private final String email;
    private final Instant regDate;

    private CustomerImmutable(Builder b) {
        this.id = b.id;
        this.email = b.email;
        this.name = b.name;
        this.regDate = b.regDate;
    }

    // This method will be automatically discovered and used by the TableSchema.
    public static Builder builder() { return new Builder(); }

    @DynamoDbPartitionKey
    public String id() { return this.id; }

    @DynamoDbSortKey
    public String email() { return this.email; }

    @DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name")
    public String name() { return this.name; }

    @DynamoDbSecondarySortKey(indexNames = {"customers_by_date", "customers_by_name"})
    public Instant regDate() { return this.regDate; }

    public static final class Builder {
        private String id;
        private String email;
        private String name;
        private Instant regDate;

        // The private Builder constructor is visible to the enclosing CustomerImmutable class.
        private Builder() {}

        public Builder id(String id) { this.id = id; return this; }
        public Builder email(String email) { this.email = email; return this; }
        public Builder name(String name) { this.name = name; return this; }
        public Builder regDate(Instant regDate) { this.regDate = regDate; return this; }

        // This method will be automatically discovered and used by the TableSchema.
        public CustomerImmutable build() { return new CustomerImmutable(this); }
    }
}
```

Sie müssen die folgenden Anforderungen erfüllen, wenn Sie eine Datenklasse mit annotieren. `@DynamoDbImmutable`

1. Jede Methode, bei der es sich nicht um eine Überschreibung von handelt `Object.class` und die nicht mit einer Anmerkung versehen wurde, `@DynamoDbIgnore` muss ein Getter für ein Attribut der DynamoDB-Tabelle sein.

1. Jeder Getter muss einen entsprechenden Setter in der Builder-Klasse haben, bei der Groß- und Kleinschreibung berücksichtigt wird.

1. Nur eine der folgenden Konstruktionsbedingungen muss erfüllt sein.
   + Die Builder-Klasse muss über einen öffentlichen Standardkonstruktor verfügen.
   + Die Datenklasse muss eine öffentliche statische Methode mit dem Namen haben`builder()`, die keine Parameter akzeptiert und eine Instanz der Builder-Klasse zurückgibt. Diese Option wird in der unveränderlichen `Customer` Klasse angezeigt.

1.  Die Builder-Klasse muss eine öffentliche Methode mit dem Namen haben`build()`, die keine Parameter akzeptiert und eine Instanz der unveränderlichen Klasse zurückgibt. 

Um eine `TableSchema` für Ihre unveränderliche Klasse zu erstellen, verwenden Sie die `fromImmutableClass()` Methode on, `TableSchema` wie im folgenden Codeausschnitt gezeigt.

```
static final TableSchema<CustomerImmutable> customerImmutableTableSchema = 
                         TableSchema.fromImmutableClass(CustomerImmutable.class);
```

So wie Sie eine DynamoDB-Tabelle aus einer veränderbaren Klasse erstellen können, können Sie eine aus einer unveränderlichen Klasse mit einem *einmaligen* Aufruf von `createTable()` of erstellen, `DynamoDbTable` wie im folgenden Codefragmentbeispiel gezeigt.

```
static void createTableFromImmutable(DynamoDbEnhancedClient enhancedClient, String tableName, DynamoDbWaiter waiter){
    // First, create an in-memory representation of the table using the 'table()' method of the DynamoDb Enhanced Client.
    // 'table()' accepts a name for the table and a TableSchema instance that you created previously.
    DynamoDbTable<CustomerImmutable> customerDynamoDbTable = enhancedClient
            .table(tableName, TableSchema.fromImmutableClass(CustomerImmutable.class));
        
    // Second, call the 'createTable()' method on the DynamoDbTable instance.
    customerDynamoDbTable.createTable();
    waiter.waitUntilTableExists(b -> b.tableName(tableName));
}
```

## Verwenden Sie Bibliotheken von Drittanbietern wie Lombok
<a name="ddb-en-client-use-immut-lombok"></a>

Bibliotheken von Drittanbietern, wie [Project Lombok](https://projectlombok.org/), helfen dabei, Standardcode zu generieren, der unveränderlichen Objekten zugeordnet ist. Die DynamoDB Enhanced Client API funktioniert mit diesen Bibliotheken, solange die Datenklassen den in diesem Abschnitt beschriebenen Konventionen entsprechen. 

Das folgende Beispiel zeigt die unveränderliche `CustomerImmutable` Klasse mit Lombok-Anmerkungen. Beachten Sie, wie die `onMethod` Funktion von Lombok attributbasierte DynamoDB-Anmerkungen, wie z. B., in den generierten Code kopiert. `@DynamoDbPartitionKey`

```
@Value
@Builder
@DynamoDbImmutable(builder = Customer.CustomerBuilder.class)
public class Customer {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;

    @Getter(onMethod_=@DynamoDbSortKey)
    private String email;

    @Getter(onMethod_=@DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name"))
    private String name;

    @Getter(onMethod_=@DynamoDbSecondarySortKey(indexNames = {"customers_by_date", "customers_by_name"}))
    private Instant createdDate;
}
```

# Verwenden Sie Ausdrücke und Bedingungen
<a name="ddb-en-client-expressions"></a>

Ausdrücke in der DynamoDB Enhanced Client API sind Java-Repräsentationen von [DynamoDB-Ausdrücken](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html).

Die DynamoDB Enhanced Client API verwendet drei Arten von Ausdrücken:

[Expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)  
Die `Expression` Klasse wird verwendet, wenn Sie Bedingungen und Filter definieren.

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)  
Dieser Ausdruckstyp stellt [wichtige Bedingungen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions) für Abfrageoperationen dar.

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html)  
Diese Klasse hilft Ihnen beim Schreiben von [DynamoDB-Aktualisierungsausdrücken](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html) und wird derzeit im Erweiterungs-Framework verwendet, wenn Sie ein Element aktualisieren.

## Anatomie des Ausdrucks
<a name="ddb-en-client-expressions-compoonents"></a>

Ein Ausdruck setzt sich wie folgt zusammen:
+ Ein Zeichenkettenausdruck (erforderlich). Die Zeichenfolge enthält einen DynamoDB-Logikausdruck mit Platzhalternamen für Attributnamen und Attributwerte.
+ Eine Zuordnung von Ausdruckswerten (normalerweise erforderlich).
+ Eine Zuordnung von Ausdrucksnamen (optional).

Verwenden Sie einen Builder, um ein `Expression` Objekt zu generieren, das die folgende allgemeine Form annimmt.

```
Expression expression = Expression.builder()
                            .expression(<String>)
                            .expressionNames(<Map>)
                            .expressionValues(<Map>)
                           .build()
```

`Expression`s erfordern normalerweise eine Zuordnung von Ausdruckswerten. Die Map stellt die Werte für die Platzhalter im Zeichenkettenausdruck bereit. Der Map-Schlüssel besteht aus dem Platzhalternamen, dem ein Doppelpunkt (`:`) vorangestellt ist, und der Zuordnungswert ist eine Instanz von. [AttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html) Die [AttributeValues](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/AttributeValues.html)Klasse verfügt über praktische Methoden zum Generieren einer `AttributeValue` Instanz aus einem Literal. Alternativ können Sie die verwenden, `AttributeValue.Builder` um eine `AttributeValue` Instanz zu generieren.

Das folgende Snippet zeigt eine Map mit zwei Einträgen nach Kommentarzeile 2. Die an die `expression()` Methode übergebene Zeichenfolge, die nach Kommentarzeile 1 angezeigt wird, enthält die Platzhalter, die DynamoDB vor der Ausführung des Vorgangs auflöst. Dieser Ausschnitt enthält keine Zuordnung von Ausdrucksnamen, da *Preis* ein zulässiger Attributname ist.

```
    public static void scanAsync(DynamoDbAsyncTable productCatalog) {
        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                .attributesToProject("id", "title", "authors", "price")
                .filterExpression(Expression.builder()
                        // 1. :min_value and :max_value are placeholders for the values provided by the map
                        .expression("price >= :min_value AND price <= :max_value")
                        // 2. Two values are needed for the expression and each is supplied as a map entry.
                        .expressionValues(
                                Map.of( ":min_value", numberValue(8.00),
                                        ":max_value", numberValue(400_000.00)))
                        .build())
                .build();
```

Wenn ein Attributname in der DynamoDB-Tabelle ein reserviertes Wort ist, mit einer Zahl beginnt oder ein Leerzeichen enthält, ist eine Zuordnung von Ausdrucksnamen für erforderlich. `Expression`

Wenn der Attributname beispielsweise `1price` anstelle von `price` im vorherigen Codebeispiel verwendet wurde, müsste das Beispiel wie im folgenden Beispiel geändert werden.

```
        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .filterExpression(Expression.builder()
                        .expression("#price >= :min_value AND #price <= :max_value")
                        .expressionNames( Map.of("#price", "1price") )
                        .expressionValues(
                                Map.of(":min_value", numberValue(8.00),
                                        ":max_value", numberValue(400_000.00)))
                        .build())
                .build();
```

Ein Platzhalter für einen Ausdrucksnamen beginnt mit dem Rautenzeichen (`#`). Ein Eintrag für die Zuordnung von Ausdrucksnamen verwendet den Platzhalter als Schlüssel und den Attributnamen als Wert. Die Map wird dem Ausdrucks-Generator mit der `expressionNames()` Methode hinzugefügt. DynamoDB löst den Attributnamen auf, bevor es den Vorgang ausführt.

Ausdruckswerte sind nicht erforderlich, wenn eine Funktion im Zeichenkettenausdruck verwendet wird. Ein Beispiel für eine Ausdrucksfunktion ist`attribute_exists(<attribute_name>)`.

Im folgenden Beispiel wird eine erstellt`Expression`, die eine [DynamoDB-Funktion](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) verwendet. Die Ausdruckszeichenfolge in diesem Beispiel verwendet keine Platzhalter. Dieser Ausdruck könnte bei einer `putItem` Operation verwendet werden, um zu überprüfen, ob in der Datenbank bereits ein Element vorhanden ist, dessen Wert dem `movie` Attribut des Datenobjekts `movie` entspricht.

```
Expression exp = Expression.builder().expression("attribute_not_exists (movie)").build();
```

Das DynamoDB Developer Guide enthält vollständige Informationen zu den [Low-Level-Ausdrücken, die mit](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html) DynamoDB verwendet werden.

## Bedingungsausdrücke und Bedingungen
<a name="ddb-en-client-expressions-cond"></a>

Wenn Sie die `deleteItem()` Methoden `putItem()``updateItem()`, und sowie Transaktions- und Batchoperationen verwenden, verwenden Sie `[Expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)` Objekte, um Bedingungen anzugeben, die DynamoDB erfüllen muss, um mit dem Vorgang fortzufahren. Diese Ausdrücke sind benannte Bedingungsausdrücke. Ein Beispiel finden Sie in dem Bedingungsausdruck, der in der `addDeleteItem()` Methode (nach Kommentarzeile 1) des [Transaktionsbeispiels](ddb-en-client-use-multiop-trans.md#ddb-en-client-use-multiop-trans-writeitems-opcondition) in dieser Anleitung verwendet wurde.

Wenn Sie mit den `query()` Methoden arbeiten, wird eine Bedingung als ausgedrückt [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html). Die `QueryConditional` Klasse verfügt über mehrere statische praktische Methoden, mit deren Hilfe Sie die Kriterien schreiben können, die bestimmen, welche Elemente aus DynamoDB gelesen werden sollen.

Beispiele `QueryConditionals` dafür finden Sie im ersten Codebeispiel des [`Query`Beispiele für Methoden](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-query-example) Abschnitts dieses Handbuchs.

## Filterausdrücke
<a name="ddb-en-client-expressions-filter"></a>

Filterausdrücke werden bei Scan- und Abfragevorgängen verwendet, um die zurückgegebenen Elemente zu filtern. 

Ein Filterausdruck wird angewendet, nachdem alle Daten aus der Datenbank gelesen wurden, sodass die Lesekosten dieselben sind, als ob es keinen Filter gäbe. Im *Amazon DynamoDB Developer Guide* finden Sie weitere Informationen zur Verwendung von Filterausdrücken für [Abfrage](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression) - und [Scanvorgänge](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.FilterExpression).

Das folgende Beispiel zeigt einen Filterausdruck, der einer Scananforderung hinzugefügt wurde. Die Kriterien beschränken die Anzahl der zurückgesendeten Artikel auf Artikel mit einem Preis zwischen 8,00 und einschließlich 80,00€.

```
        Map<String, AttributeValue> expressionValues = Map.of(
                ":min_value", numberValue(8.00),
                ":max_value", numberValue(80.00));

        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                // 1. the 'attributesToProject()' method allows you to specify which values you want returned.
                .attributesToProject("id", "title", "authors", "price")
                // 2. Filter expression limits the items returned that match the provided criteria.
                .filterExpression(Expression.builder()
                        .expression("price >= :min_value AND price <= :max_value")
                        .expressionValues(expressionValues)
                        .build())
                .build();
```

## Aktualisierungsausdrücke
<a name="ddb-en-client-expressions-update"></a>

Die Methode des DynamoDB Enhanced Client bietet eine `updateItem()` Standardmethode zum Aktualisieren von Elementen in DynamoDB. Wenn Sie jedoch mehr Funktionen benötigen, [UpdateExpressions](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html)stellen Sie eine typsichere Darstellung der Syntax von [DynamoDB-Aktualisierungsausdrücken](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html) bereit. Sie können es beispielsweise verwenden, um Werte `UpdateExpressions` zu erhöhen, ohne zuerst Elemente aus DynamoDB zu lesen, oder um einzelne Mitglieder zu einer Liste hinzuzufügen. Aktualisierungsausdrücke sind derzeit in benutzerdefinierten Erweiterungen für die `updateItem()` Methode verfügbar.

Ein Beispiel, das Aktualisierungsausdrücke verwendet, finden Sie im [Beispiel für eine benutzerdefinierte Erweiterung](ddb-en-client-extensions-custom.md) in diesem Handbuch.

Weitere Informationen zu Aktualisierungsausdrücken finden Sie im [Amazon DynamoDB Developer Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html).

# Arbeiten Sie mit paginierten Ergebnissen: Scans und Abfragen
<a name="ddb-en-client-use-multirecord"></a>

*Die `scan` `batch` Methoden `query` und der DynamoDB Enhanced Client API geben Antworten mit einer oder mehreren Seiten zurück.* Eine Seite enthält ein oder mehrere Elemente. Ihr Code kann die Antwort pro Seite oder einzelne Elemente verarbeiten.

Eine vom synchronen Client zurückgegebene paginierte Antwort gibt ein [PageIterable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PageIterable.html)Objekt zurück, wohingegen eine vom asynchronen `DynamoDbEnhancedClient` `DynamoDbEnhancedAsyncClient` Client zurückgegebene Antwort ein Objekt zurückgibt. [PagePublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PagePublisher.html)

Dieser Abschnitt befasst sich mit der Verarbeitung paginierter Ergebnisse und enthält Beispiele für die Verwendung von Scan und Abfrage. APIs

## Scannen einer Tabelle
<a name="ddb-en-client-use-multirecord-scan"></a>

Die [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.html#scan(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.html#scan(java.util.function.Consumer))Methode des SDK entspricht der gleichnamigen [DynamoDB-Operation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html). Die DynamoDB Enhanced Client API bietet dieselben Optionen, verwendet jedoch ein vertrautes Objektmodell und übernimmt die Paginierung für Sie.

Zunächst untersuchen wir die `PageIterable` Schnittstelle, indem wir uns die `scan` Methode der synchronen Mapping-Klasse ansehen. [DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)

### Verwenden Sie die synchrone API
<a name="ddb-en-client-use-multirecord-scan-sync"></a>

Das folgende Beispiel zeigt die `scan` Methode, die einen [Ausdruck](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html) verwendet, um die zurückgegebenen Elemente zu filtern. Das [ProductCatalog](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)ist das Modellobjekt, das zuvor gezeigt wurde.

Der nach Kommentarzeile 2 angezeigte Filterausdruck beschränkt die Anzahl der zurückgegebenen `ProductCatalog` Artikel auf Artikel mit einem Preiswert zwischen 8,00 und 80,00 (einschließlich).

In diesem Beispiel werden auch die `isbn` Werte ausgeschlossen, indem die `attributesToProject` Methode verwendet wird, die nach Kommentarzeile 1 gezeigt wird.

Nach Kommentarzeile 3 wird das `PageIterable` Objekt,`pagedResults`, von der `scan` Methode zurückgegeben. Die `stream` Methode von `PageIterable` gibt ein [https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)Objekt zurück, mit dem Sie die Seiten bearbeiten können. In diesem Beispiel wird die Anzahl der Seiten gezählt und protokolliert.

Beginnend mit Kommentarzeile 4 zeigt das Beispiel zwei Varianten des Zugriffs auf die `ProductCatalog` Elemente. Die Version nach der Kommentarzeile 4a durchläuft jede Seite und sortiert und protokolliert die Elemente auf jeder Seite. Die Version nach der Kommentarzeile 4b überspringt die Seiteniteration und greift direkt auf die Elemente zu.

Die `PageIterable` Schnittstelle bietet aufgrund ihrer beiden übergeordneten Schnittstellen — und — mehrere Möglichkeiten zur Verarbeitung von Ergebnissen. [https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html](https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html) `Iterable`bringt `forEach` die `spliterator` Methoden `iterator` und und `SdkIterable` bringt die `stream` Methode.

```
    public static void scanSync(DynamoDbTable<ProductCatalog> productCatalog) {

        Map<String, AttributeValue> expressionValues = Map.of(
                ":min_value", numberValue(8.00),
                ":max_value", numberValue(80.00));

        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                // 1. the 'attributesToProject()' method allows you to specify which values you want returned.
                .attributesToProject("id", "title", "authors", "price")
                // 2. Filter expression limits the items returned that match the provided criteria.
                .filterExpression(Expression.builder()
                        .expression("price >= :min_value AND price <= :max_value")
                        .expressionValues(expressionValues)
                        .build())
                .build();

        // 3. A PageIterable object is returned by the scan method.
        PageIterable<ProductCatalog> pagedResults = productCatalog.scan(request);
        logger.info("page count: {}", pagedResults.stream().count());

        // 4. Log the returned ProductCatalog items using two variations.
        // 4a. This version sorts and logs the items of each page.
        pagedResults.stream().forEach(p -> p.items().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(
                        item -> logger.info(item.toString())
                ));
        // 4b. This version sorts and logs all items for all pages.
        pagedResults.items().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(
                        item -> logger.info(item.toString())
                );
    }
```

### Verwenden Sie die asynchrone API
<a name="ddb-en-client-use-multirecord-scan-async"></a>

Die asynchrone `scan` Methode gibt Ergebnisse als `PagePublisher` Objekt zurück. Die `PagePublisher` Schnittstelle verfügt über zwei `subscribe` Methoden, mit denen Sie Antwortseiten verarbeiten können. Eine `subscribe` Methode stammt von der `org.reactivestreams.Publisher` übergeordneten Schnittstelle. Um Seiten mit dieser ersten Option zu verarbeiten, übergeben Sie der `subscribe` Methode eine `[Subscriber](https://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/org/reactivestreams/Subscriber.html)` Instanz. Das erste Beispiel, das folgt, zeigt die Verwendung der `subscribe` Methode.

Die zweite `subscribe` Methode stammt von der [SdkPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html)Schnittstelle. Diese Version von `subscribe` akzeptiert [https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html](https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html)eher a als `Subscriber` a. Diese `subscribe` Methodenvariante wird im zweiten Beispiel gezeigt, das folgt.

Das folgende Beispiel zeigt die asynchrone Version der `scan` Methode, die denselben Filterausdruck wie im vorherigen Beispiel verwendet. 

Gibt nach Kommentarzeile 3 ein `PagePublisher` Objekt `DynamoDbAsyncTable.scan` zurück. In der nächsten Zeile erstellt der Code eine Instanz der `org.reactivestreams.Subscriber` Schnittstelle`ProductCatalogSubscriber`, die die vierte Zeile `PagePublisher` nach dem Kommentar abonniert.

Das `Subscriber` Objekt sammelt die `ProductCatalog` Elemente von jeder Seite in der `onNext` Methode nach der Kommentarzeile 8 im `ProductCatalogSubscriber` Klassenbeispiel. Die Elemente werden in der privaten `List` Variablen gespeichert und im aufrufenden Code mit der `ProductCatalogSubscriber.getSubscribedItems()` Methode aufgerufen. Dies wird nach Kommentarzeile 5 aufgerufen.

Nachdem die Liste abgerufen wurde, sortiert der Code alle `ProductCatalog` Artikel nach Preis und protokolliert jeden Artikel.

Die Klasse [CountDownLatch](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)in der `ProductCatalogSubscriber` Klasse blockiert den aufrufenden Thread, bis alle Elemente zur Liste hinzugefügt wurden, bevor sie nach Kommentarzeile 5 weitermacht. 

```
    public static void scanAsync(DynamoDbAsyncTable productCatalog) {
        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                .attributesToProject("id", "title", "authors", "price")
                .filterExpression(Expression.builder()
                        // 1. :min_value and :max_value are placeholders for the values provided by the map
                        .expression("price >= :min_value AND price <= :max_value")
                        // 2. Two values are needed for the expression and each is supplied as a map entry.
                        .expressionValues(
                                Map.of( ":min_value", numberValue(8.00),
                                        ":max_value", numberValue(400_000.00)))
                        .build())
                .build();

        // 3. A PagePublisher object is returned by the scan method.
        PagePublisher<ProductCatalog> pagePublisher = productCatalog.scan(request);
        ProductCatalogSubscriber subscriber = new ProductCatalogSubscriber();
        // 4. Subscribe the ProductCatalogSubscriber to the PagePublisher.
        pagePublisher.subscribe(subscriber);
        // 5. Retrieve all collected ProductCatalog items accumulated by the subscriber.
        subscriber.getSubscribedItems().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(item ->
                        logger.info(item.toString()));
        // 6. Use a Consumer to work through each page.
        pagePublisher.subscribe(page -> page
                        .items().stream()
                        .sorted(Comparator.comparing(ProductCatalog::price))
                        .forEach(item ->
                                logger.info(item.toString())))
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
        // 7. Use a Consumer to work through each ProductCatalog item.
        pagePublisher.items()
                .subscribe(product -> logger.info(product.toString()))
                .exceptionally(failure -> {
                    logger.error("ERROR  - ", failure);
                    return null;
                })
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
    }
```

```
    private static class ProductCatalogSubscriber implements Subscriber<Page<ProductCatalog>> {
        private CountDownLatch latch = new CountDownLatch(1);
        private Subscription subscription;
        private List<ProductCatalog> itemsFromAllPages = new ArrayList<>();

        @Override
        public void onSubscribe(Subscription sub) {
            subscription = sub;
            subscription.request(1L);
            try {
                latch.await(); // Called by main thread blocking it until latch is released.
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void onNext(Page<ProductCatalog> productCatalogPage) {
            // 8. Collect all the ProductCatalog instances in the page, then ask the publisher for one more page.
            itemsFromAllPages.addAll(productCatalogPage.items());
            subscription.request(1L);
        }

        @Override
        public void onError(Throwable throwable) {
        }

        @Override
        public void onComplete() {
            latch.countDown(); // Call by subscription thread; latch releases.
        }

        List<ProductCatalog> getSubscribedItems() {
            return this.itemsFromAllPages;
        }
    }
```

Das folgende Codefragmentbeispiel verwendet die Version der `PagePublisher.subscribe` Methode, die eine Eingabe `Consumer` nach der Kommentarzeile 6 akzeptiert. Der Java-Lambda-Parameter verbraucht Seiten, die jedes Element weiterverarbeiten. In diesem Beispiel wird jede Seite verarbeitet und die Elemente auf jeder Seite werden sortiert und anschließend protokolliert.

```
        // 6. Use a Consumer to work through each page.
        pagePublisher.subscribe(page -> page
                        .items().stream()
                        .sorted(Comparator.comparing(ProductCatalog::price))
                        .forEach(item ->
                                logger.info(item.toString())))
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
```

Die `items` Methode `PagePublisher` entpackt die Modellinstanzen, sodass Ihr Code die Elemente direkt verarbeiten kann. Dieser Ansatz wird im folgenden Snippet gezeigt.

```
        // 7. Use a Consumer to work through each ProductCatalog item.
        pagePublisher.items()
                .subscribe(product -> logger.info(product.toString()))
                .exceptionally(failure -> {
                    logger.error("ERROR  - ", failure);
                    return null;
                })
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
```

## Tabellen abfragen
<a name="ddb-en-client-use-multirecord-query"></a>

Sie können den DynamoDB Enhanced Client verwenden, um Ihre Tabelle abzufragen und mehrere Elemente abzurufen, die bestimmten Kriterien entsprechen. Die [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#query(software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#query(software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest))Methode findet Elemente auf der Grundlage von Primärschlüsselwerten anhand der `@DynamoDbPartitionKey` und optionaler `@DynamoDbSortKey` Anmerkungen, die in Ihrer Datenklasse definiert sind.

Die `query()` Methode erfordert einen Partitionsschlüsselwert und akzeptiert optional Sortierschlüsselbedingungen, um die Ergebnisse weiter zu verfeinern. Wie die `scan` API geben Abfragen a `PageIterable` für synchrone Aufrufe und a `PagePublisher` für asynchrone Aufrufe zurück.

### `Query`Beispiele für Methoden
<a name="ddb-en-client-use-multirecord-query-example"></a>

Das folgende `query()` Methodencodebeispiel verwendet die `MovieActor` Klasse. Die Datenklasse definiert einen zusammengesetzten Primärschlüssel, der aus dem **`movie`**Attribut als Partitionsschlüssel und dem **`actor`**Attribut als Sortierschlüssel besteht. 

#### `MovieActor`-Klasse
<a name="ddb-en-client-use-movieactor-class"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.util.Objects;

@DynamoDbBean
public class MovieActor implements Comparable<MovieActor> {

    private String movieName;
    private String actorName;
    private String actingAward;
    private Integer actingYear;
    private String actingSchoolName;

    @DynamoDbPartitionKey
    @DynamoDbAttribute("movie")
    public String getMovieName() {
        return movieName;
    }

    public void setMovieName(String movieName) {
        this.movieName = movieName;
    }

    @DynamoDbSortKey
    @DynamoDbAttribute("actor")
    public String getActorName() {
        return actorName;
    }

    public void setActorName(String actorName) {
        this.actorName = actorName;
    }

    @DynamoDbSecondaryPartitionKey(indexNames = "acting_award_year")
    @DynamoDbAttribute("actingaward")
    public String getActingAward() {
        return actingAward;
    }

    public void setActingAward(String actingAward) {
        this.actingAward = actingAward;
    }

    @DynamoDbSecondarySortKey(indexNames = {"acting_award_year", "movie_year"})
    @DynamoDbAttribute("actingyear")
    public Integer getActingYear() {
        return actingYear;
    }

    public void setActingYear(Integer actingYear) {
        this.actingYear = actingYear;
    }

    @DynamoDbAttribute("actingschoolname")
    public String getActingSchoolName() {
        return actingSchoolName;
    }

    public void setActingSchoolName(String actingSchoolName) {
        this.actingSchoolName = actingSchoolName;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("MovieActor{");
        sb.append("movieName='").append(movieName).append('\'');
        sb.append(", actorName='").append(actorName).append('\'');
        sb.append(", actingAward='").append(actingAward).append('\'');
        sb.append(", actingYear=").append(actingYear);
        sb.append(", actingSchoolName='").append(actingSchoolName).append('\'');
        sb.append('}');
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MovieActor that = (MovieActor) o;
        return Objects.equals(movieName, that.movieName) && Objects.equals(actorName, that.actorName) && Objects.equals(actingAward, that.actingAward) && Objects.equals(actingYear, that.actingYear) && Objects.equals(actingSchoolName, that.actingSchoolName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(movieName, actorName, actingAward, actingYear, actingSchoolName);
    }

    @Override
    public int compareTo(MovieActor o) {
        if (this.movieName.compareTo(o.movieName) != 0){
            return this.movieName.compareTo(o.movieName);
        } else {
            return this.actorName.compareTo(o.actorName);
        }
    }
}
```

In den folgenden Codebeispielen werden die folgenden Elemente abgefragt.

#### Elemente in der `MovieActor` Tabelle
<a name="ddb-en-client-use-movieactor-items"></a>

```
MovieActor{movieName='movie01', actorName='actor0', actingAward='actingaward0', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
MovieActor{movieName='movie02', actorName='actor0', actingAward='actingaward0', actingYear=2002, actingSchoolName='null'}
MovieActor{movieName='movie02', actorName='actor1', actingAward='actingaward1', actingYear=2002, actingSchoolName='actingschool1'}
MovieActor{movieName='movie02', actorName='actor2', actingAward='actingaward2', actingYear=2002, actingSchoolName='actingschool2'}
MovieActor{movieName='movie02', actorName='actor3', actingAward='actingaward3', actingYear=2002, actingSchoolName='null'}
MovieActor{movieName='movie02', actorName='actor4', actingAward='actingaward4', actingYear=2002, actingSchoolName='actingschool4'}
MovieActor{movieName='movie03', actorName='actor0', actingAward='actingaward0', actingYear=2003, actingSchoolName='null'}
MovieActor{movieName='movie03', actorName='actor1', actingAward='actingaward1', actingYear=2003, actingSchoolName='actingschool1'}
MovieActor{movieName='movie03', actorName='actor2', actingAward='actingaward2', actingYear=2003, actingSchoolName='actingschool2'}
MovieActor{movieName='movie03', actorName='actor3', actingAward='actingaward3', actingYear=2003, actingSchoolName='null'}
MovieActor{movieName='movie03', actorName='actor4', actingAward='actingaward4', actingYear=2003, actingSchoolName='actingschool4'}
```

Der folgende Code definiert zwei `QueryConditional` Instanzen: `keyEqual` (nach Kommentarzeile 1) und `sortGreaterThanOrEqualTo` (nach Kommentarzeile 1a).

#### Fragen Sie Elemente anhand des Partitionsschlüssels ab
<a name="keyEqual-query-conditional-example"></a>

Die `keyEqual` Instanz gleicht Elementen mit einem Partitionsschlüsselwert von ab **`movie01`**. 

In diesem Beispiel wird auch ein Filterausdruck nach Kommentarzeile 2 definiert, der alle Elemente herausfiltert, die keinen **`actingschoolname`**Wert haben.

Der `QueryEnhancedRequest` kombiniert die Schlüsselbedingung und den Filterausdruck für die Abfrage.

```
    public static void query(DynamoDbTable movieActorTable) {

        // 1. Define a QueryConditional instance to return items matching a partition value.
        QueryConditional keyEqual = QueryConditional.keyEqualTo(b -> b.partitionValue("movie01"));
        // 1a. Define a QueryConditional that adds a sort key criteria to the partition value criteria.
        QueryConditional sortGreaterThanOrEqualTo = QueryConditional.sortGreaterThanOrEqualTo(b -> b.partitionValue("movie01").sortValue("actor2"));
        // 2. Define a filter expression that filters out items whose attribute value is null.
        final Expression filterOutNoActingschoolname = Expression.builder().expression("attribute_exists(actingschoolname)").build();

        // 3. Build the query request.
        QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()
                .queryConditional(keyEqual)
                .filterExpression(filterOutNoActingschoolname)
                .build();
        // 4. Perform the query using the "keyEqual" conditional and filter expression.
        PageIterable<MovieActor> pagedResults = movieActorTable.query(tableQuery);
        logger.info("page count: {}", pagedResults.stream().count()); // Log  number of pages.

        pagedResults.items().stream()
                .sorted()
                .forEach(
                        item -> logger.info(item.toString()) // Log the sorted list of items.
                );
```

**Example — Ausgabe unter Verwendung der `keyEqual` Abfragebedingung**  
Das Folgende ist die Ausgabe der Ausführung der Methode. In der Ausgabe werden Elemente mit dem `movieName` Wert **movie01** und keine Elemente mit dem Wert `actingSchoolName` gleich angezeigt. **`null`**  

```
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:46 - page count: 1
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```

#### Fragen Sie Elemente nach Partitionsschlüssel und Sortierschlüssel ab
<a name="sort-type-query-conditional-example"></a>

**Der `sortGreaterThanOrEqualTo` `QueryConditional` verfeinert die Übereinstimmung mit den Partitionsschlüsseln (**movie01**), indem eine Sortierschlüsselbedingung für Werte hinzugefügt wird, die größer oder gleich actor2 sind.**

[`QueryConditional`Methoden](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html), die mit beginnen, `sort` erfordern, dass ein Partitionsschlüsselwert übereinstimmt und die Abfrage durch einen Vergleich auf der Grundlage des Sortierschlüsselwerts weiter verfeinert wird. `Sort`bedeutet im Methodennamen nicht, dass die Ergebnisse sortiert sind, sondern dass ein Sortierschlüsselwert für den Vergleich verwendet wird.

Im folgenden Snippet ändern wir die Abfrageanfrage, die zuvor nach Kommentarzeile 3 angezeigt wurde. Dieses Snippet ersetzt die Abfragebedingung „keyEqual“ durch die Abfragebedingung "sortGreaterThanOrEqualTo", die nach der Kommentarzeile 1a definiert wurde. Der folgende Code entfernt auch den Filterausdruck.

```
        QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()
                .queryConditional(sortGreaterThanOrEqualTo).build();
```

**Example — Ausgabe unter Verwendung der `sortGreaterThanOrEqualTo` Abfragebedingung**  
In der folgenden Ausgabe werden die Ergebnisse der Abfrage angezeigt. **Die Abfrage gibt Elemente zurück, deren `movieName` Wert **movie01** entspricht, und nur Elemente, deren `actorName` Wert größer oder gleich actor2 ist.** Da wir den Filter entfernen, gibt die Abfrage Elemente zurück, die keinen Wert für das Attribut haben. `actingSchoolName`  

```
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:46 - page count: 1
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```

# Führen Sie Batch-Operationen durch
<a name="ddb-en-client-use-multiop-batch"></a>

Die DynamoDB Enhanced Client API bietet zwei Batch-Methoden, [`batchGetItem`()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchGetItem(java.util.function.Consumer)) und [`batchWriteItem`(](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchWriteItem(java.util.function.Consumer))).

## `batchGetItem()`Beispiel für
<a name="ddb-en-client-use-multiop-batch-get"></a>

Mit [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchGetItem(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchGetItem(java.util.function.Consumer))dieser Methode können Sie bis zu 100 einzelne Elemente aus mehreren Tabellen in einer Gesamtanforderung abrufen. Im folgenden Beispiel werden die zuvor gezeigten [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)Datenklassen [`Customer`](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust)und verwendet.

Im Beispiel nach den Zeilen 1 und 2 erstellen Sie `[ReadBatch](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ReadBatch.html)` Objekte, die Sie später nach Kommentarzeile 3 als Parameter `batchGetItem()` zur Methode hinzufügen. 

Der Code nach der ersten Kommentarzeile erstellt den Batch, der aus der `Customer` Tabelle gelesen werden soll. Der Code nach der Kommentarzeile 1a zeigt die Verwendung eines `[GetItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/GetItemEnhancedRequest.Builder.html)` Builders, der einen Primärschlüsselwert und einen Sortierschlüsselwert verwendet, um das zu lesende Element anzugeben. Wenn die Datenklasse über einen zusammengesetzten Schlüssel verfügt, müssen Sie sowohl den Partitionsschlüsselwert als auch den Sortierschlüsselwert angeben. 

Im Gegensatz zur Angabe von Schlüsselwerten für die Anforderung eines Elements können Sie eine Datenklasse verwenden, um ein Element anzufordern, wie nach Kommentarzeile 1b gezeigt. Das SDK extrahiert die Schlüsselwerte hinter den Kulissen, bevor die Anfrage gesendet wird.

[Wenn Sie das Element mithilfe des schlüsselbasierten Ansatzes angeben, wie in den beiden Anweisungen nach 2a gezeigt, können Sie auch angeben, dass DynamoDB einen stark konsistenten Lesevorgang durchführen soll.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html) Wenn die `consistentRead()` Methode verwendet wird, muss sie für alle angeforderten Elemente für dieselbe Tabelle verwendet werden.

Verwenden Sie die `[resultsForTable() ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#resultsForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` Methode, die nach Kommentarzeile 4 angezeigt wird, um die von DynamoDB gefundenen Elemente abzurufen. Rufen Sie die Methode für jede Tabelle auf, die in der Anforderung gelesen wurde. `resultsForTable()`gibt eine Liste der gefundenen Elemente zurück, die Sie mit einer beliebigen `java.util.List` Methode verarbeiten können. In diesem Beispiel wird jedes Element protokolliert.

Um Elemente zu finden, die DynamoDB nicht verarbeitet hat, verwenden Sie den Ansatz nach Kommentarzeile 5. Die `BatchGetResultPage` Klasse verfügt über die `[unprocessedKeysForTable()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#unprocessedKeysForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` Methode, mit der Sie auf jeden Schlüssel zugreifen können, der nicht verarbeitet wurde. Die [BatchGetItem API-Referenz](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html) enthält weitere Informationen zu Situationen, die zu unverarbeiteten Elementen führen.

```
    public static void batchGetItemExample(DynamoDbEnhancedClient enhancedClient,
                                           DynamoDbTable<Customer> customerTable,
                                           DynamoDbTable<MovieActor> movieActorTable) {

        Customer customer2 = new Customer();
        customer2.setId("2");
        customer2.setEmail("cust2@example.org");

        // 1. Build a batch to read from the Customer table.
        ReadBatch customerBatch = ReadBatch.builder(Customer.class)
                .mappedTableResource(customerTable)
                // 1a. Specify the primary key value and sort key value for the item.
                .addGetItem(b -> b.key(k -> k.partitionValue("1").sortValue("cust1@orgname.org")))
                // 1b. Alternatively, supply a data class instances to provide the primary key values.
                .addGetItem(customer2)
                .build();

        // 2. Build a batch to read from the MovieActor table.
        ReadBatch moveActorBatch = ReadBatch.builder(MovieActor.class)
                .mappedTableResource(movieActorTable)
                // 2a. Call consistentRead(Boolean.TRUE) for each item for the same table.
                .addGetItem(b -> b.key(k -> k.partitionValue("movie01").sortValue("actor1")).consistentRead(Boolean.TRUE))
                .addGetItem(b -> b.key(k -> k.partitionValue("movie01").sortValue("actor4")).consistentRead(Boolean.TRUE))
                .build();

        // 3. Add ReadBatch objects to the request.
        BatchGetResultPageIterable resultPages = enhancedClient.batchGetItem(b -> b.readBatches(customerBatch, moveActorBatch));

        // 4. Retrieve the successfully requested items from each table.
        resultPages.resultsForTable(customerTable).forEach(item -> logger.info(item.toString()));
        resultPages.resultsForTable(movieActorTable).forEach(item -> logger.info(item.toString()));

        // 5. Retrieve the keys of the items requested but not processed by the service.
        resultPages.forEach((BatchGetResultPage pageResult) -> {
            pageResult.unprocessedKeysForTable(customerTable).forEach(key -> logger.info("Unprocessed item key: " + key.toString()));
            pageResult.unprocessedKeysForTable(movieActorTable).forEach(key -> logger.info("Unprocessed item key: " + key.toString()));
        });
    }
```

Gehen Sie davon aus, dass sich die folgenden Elemente in den beiden Tabellen befinden, bevor Sie den Beispielcode ausführen.

### Elemente in Tabellen
<a name="ddb-en-client-use-multiop-batch-get-tableitems"></a>

```
Customer [id=1, name=CustName1, email=cust1@example.org, regDate=2023-03-31T15:46:27.688Z]
Customer [id=2, name=CustName2, email=cust2@example.org, regDate=2023-03-31T15:46:28.688Z]
Customer [id=3, name=CustName3, email=cust3@example.org, regDate=2023-03-31T15:46:29.688Z]
Customer [id=4, name=CustName4, email=cust4@example.org, regDate=2023-03-31T15:46:30.688Z]
Customer [id=5, name=CustName5, email=cust5@example.org, regDate=2023-03-31T15:46:31.689Z]
MovieActor{movieName='movie01', actorName='actor0', actingAward='actingaward0', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```

Die folgende Ausgabe zeigt die zurückgegebenen und protokollierten Elemente nach Kommentarzeile 4.

```
Customer [id=1, name=CustName1, email=cust1@example.org, regDate=2023-03-31T15:46:27.688Z]
Customer [id=2, name=CustName2, email=cust2@example.org, regDate=2023-03-31T15:46:28.688Z]
MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
```

## `batchWriteItem()`Beispiel für
<a name="ddb-en-client-use-multiop-batch-write"></a>

Die `batchWriteItem()` Methode fügt mehrere Elemente in eine oder mehrere Tabellen ein oder löscht sie. Sie können bis zu 25 einzelne Put- oder Löschvorgänge in der Anfrage angeben. Im folgenden Beispiel werden die zuvor gezeigten Klassen [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)und [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)Modellklassen verwendet.

`WriteBatch`Objekte werden nach den Kommentarzeilen 1 und 2 erstellt. Für die `ProductCatalog` Tabelle fügt der Code ein Element ein und löscht ein Element. Für die `MovieActor` Tabelle nach Kommentarzeile 2 fügt der Code zwei Elemente ein und löscht eines.

Die `batchWriteItem` Methode wird nach Kommentarzeile 3 aufgerufen. Der `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteItemEnhancedRequest.Builder.html)` Parameter stellt die Batch-Anfragen für jede Tabelle bereit.

Das zurückgegebene `[BatchWriteResult](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteResult.html)` Objekt bietet separate Methoden für jeden Vorgang, um unverarbeitete Anfragen anzuzeigen. Der Code nach der Kommentarzeile 4a stellt die Schlüssel für unverarbeitete Löschanfragen bereit und der Code nach der Kommentarzeile 4b stellt die unverarbeiteten PUT-Elemente bereit.

```
    public static void batchWriteItemExample(DynamoDbEnhancedClient enhancedClient,
                                             DynamoDbTable<ProductCatalog> catalogTable,
                                             DynamoDbTable<MovieActor> movieActorTable) {

        // 1. Build a batch to write to the ProductCatalog table.
        WriteBatch products = WriteBatch.builder(ProductCatalog.class)
                .mappedTableResource(catalogTable)
                .addPutItem(b -> b.item(getProductCatItem1()))
                .addDeleteItem(b -> b.key(k -> k
                        .partitionValue(getProductCatItem2().id())
                        .sortValue(getProductCatItem2().title())))
                .build();

        // 2. Build a batch to write to the MovieActor table.
        WriteBatch movies = WriteBatch.builder(MovieActor.class)
                .mappedTableResource(movieActorTable)
                .addPutItem(getMovieActorYeoh())
                .addPutItem(getMovieActorBlanchettPartial())
                .addDeleteItem(b -> b.key(k -> k
                        .partitionValue(getMovieActorStreep().getMovieName())
                        .sortValue(getMovieActorStreep().getActorName())))
                .build();

        // 3. Add WriteBatch objects to the request.
        BatchWriteResult batchWriteResult = enhancedClient.batchWriteItem(b -> b.writeBatches(products, movies));
        // 4. Retrieve keys for items the service did not process.
        // 4a. 'unprocessedDeleteItemsForTable()' returns keys for delete requests that did not process.
        if (batchWriteResult.unprocessedDeleteItemsForTable(movieActorTable).size() > 0) {
            batchWriteResult.unprocessedDeleteItemsForTable(movieActorTable).forEach(key ->
                    logger.info(key.toString()));
        }
        // 4b. 'unprocessedPutItemsForTable()' returns keys for put requests that did not process.
        if (batchWriteResult.unprocessedPutItemsForTable(catalogTable).size() > 0) {
            batchWriteResult.unprocessedPutItemsForTable(catalogTable).forEach(key ->
                    logger.info(key.toString()));
        }
    }
```

Die folgenden Hilfsmethoden stellen die Modellobjekte für die Put- und Delete-Operationen bereit.

### Hilfsmethoden
<a name="ddb-en-client-use-multiop-batch-write-helpers"></a>

```
 1.     public static ProductCatalog getProductCatItem1() {
 2.         return ProductCatalog.builder()
 3.                 .id(2)
 4.                 .isbn("1-565-85698")
 5.                 .authors(new HashSet<>(Arrays.asList("a", "b")))
 6.                 .price(BigDecimal.valueOf(30.22))
 7.                 .title("Title 55")
 8.                 .build();
 9.     }
10. 
11.     public static ProductCatalog getProductCatItem2() {
12.         return ProductCatalog.builder()
13.                 .id(4)
14.                 .price(BigDecimal.valueOf(40.00))
15.                 .title("Title 1")
16.                 .build();
17.     }  
18. 
19.     public static MovieActor getMovieActorBlanchettPartial() {
20.         MovieActor movieActor = new MovieActor();
21.         movieActor.setActorName("Cate Blanchett");
22.         movieActor.setMovieName("Blue Jasmine");
23.         movieActor.setActingYear(2023);
24.         movieActor.setActingAward("Best Actress");
25.         return movieActor;
26.     }
27. 
28.     public static MovieActor getMovieActorStreep() {
29.         MovieActor movieActor = new MovieActor();
30.         movieActor.setActorName("Meryl Streep");
31.         movieActor.setMovieName("Sophie's Choice");
32.         movieActor.setActingYear(1982);
33.         movieActor.setActingAward("Best Actress");
34.         movieActor.setActingSchoolName("Yale School of Drama");
35.         return movieActor;
36.     }
37. 
38.     public static MovieActor getMovieActorYeoh(){
39.         MovieActor movieActor = new MovieActor();
40.         movieActor.setActorName("Michelle Yeoh");
41.         movieActor.setMovieName("Everything Everywhere All at Once");
42.         movieActor.setActingYear(2023);
43.         movieActor.setActingAward("Best Actress");
44.         movieActor.setActingSchoolName("Royal Academy of Dance");
45.         return movieActor;
46.     }
```

Gehen Sie davon aus, dass die Tabellen die folgenden Elemente enthalten, bevor Sie den Beispielcode ausführen.

```
MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
```

Nach Abschluss des Beispielcodes enthalten die Tabellen die folgenden Elemente.

```
MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='null'}
MovieActor{movieName='Everything Everywhere All at Once', actorName='Michelle Yeoh', actingAward='Best Actress', actingYear=2023, actingSchoolName='Royal Academy of Dance'}
ProductCatalog{id=2, title='Title 55', isbn='1-565-85698', authors=[a, b], price=30.22}
```

Beachten Sie in der `MovieActor` Tabelle, dass das `Blue Jasmine` Filmelement durch das Element ersetzt wurde, das in der Put-Anfrage verwendet wurde, die mit der `getMovieActorBlanchettPartial()` Helper-Methode abgerufen wurde. Wenn kein Data-Bean-Attributwert angegeben wurde, wird der Wert in der Datenbank entfernt. Aus diesem Grund ist das Ergebnis `actingSchoolName` für das `Blue Jasmine` Filmelement Null.

**Anmerkung**  
In der API-Dokumentation wird zwar darauf hingewiesen, dass Bedingungsausdrücke verwendet werden können und dass verbrauchte Kapazität und Erfassungsmetriken mit einzelnen [Put](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PutItemEnhancedRequest.html) - und [Löschanforderungen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/DeleteItemEnhancedRequest.html) zurückgegeben werden können, dies ist jedoch in einem Batch-Write-Szenario nicht der Fall. Um die Leistung von Batch-Vorgängen zu verbessern, werden diese einzelnen Optionen ignoriert.

# Führen Sie Transaktionsoperationen durch
<a name="ddb-en-client-use-multiop-trans"></a>

Die DynamoDB Enhanced Client API stellt die `transactGetItems()` und die `transactWriteItems()` Methoden bereit. Die Transaktionsmethoden des SDK for Java sorgen für Atomizität, Konsistenz, Isolierung und Haltbarkeit (ACID) in DynamoDB-Tabellen und helfen Ihnen so, die Datenkorrektheit in Ihren Anwendungen aufrechtzuerhalten.

## `transactGetItems()`Beispiel für
<a name="ddb-en-client-use-multiop-trans-getitems"></a>

Die `[transactGetItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactGetItems(java.util.function.Consumer))` Methode akzeptiert bis zu 100 individuelle Anfragen für Elemente. Alle Elemente werden in einer einzigen atomaren Transaktion gelesen. Das *Amazon DynamoDB DynamoDB-Entwicklerhandbuch* enthält Informationen zu den [Bedingungen, die dazu führen, dass eine `transactGetItems()` Methode fehlschlägt](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txgetitems), sowie über die Isolationsstufe, die beim Aufrufen verwendet wird. `[transactGetItem()](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-isolation)`

Nach Kommentarzeile 1 im folgenden Beispiel ruft der Code die `transactGetItems()` Methode mit einem `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactGetItemsEnhancedRequest.Builder.html)` Parameter auf. Der Builder `[addGetItem()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactGetItemsEnhancedRequest.Builder.html#addGetItem(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource,T))` wird dreimal mit einem Datenobjekt aufgerufen, das die Schlüsselwerte enthält, die das SDK verwendet, um die endgültige Anfrage zu generieren.

Die Anfrage gibt nach Kommentarzeile 2 eine Liste von `[Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html)` Objekten zurück. Die zurückgegebene Dokumentenliste enthält [Dokumentinstanzen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html) von Elementdaten, die nicht Null sind, und zwar in derselben Reihenfolge wie angefordert. Die `[Document.getItem(MappedTableResource<T> mappedTableResource)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html#getItem(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` Methode konvertiert ein untypisiertes `Document` Objekt in ein typisiertes Java-Objekt, wenn Elementdaten zurückgegeben wurden, andernfalls gibt die Methode Null zurück.

```
    public static void transactGetItemsExample(DynamoDbEnhancedClient enhancedClient,
                                               DynamoDbTable<ProductCatalog> catalogTable,
                                               DynamoDbTable<MovieActor> movieActorTable) {

        // 1. Request three items from two tables using a builder.
        final List<Document> documents = enhancedClient.transactGetItems(b -> b
                .addGetItem(catalogTable, Key.builder().partitionValue(2).sortValue("Title 55").build())
                .addGetItem(movieActorTable, Key.builder().partitionValue("Sophie's Choice").sortValue("Meryl Streep").build())
                .addGetItem(movieActorTable, Key.builder().partitionValue("Blue Jasmine").sortValue("Cate Blanchett").build())
                .build());

        // 2. A list of Document objects is returned in the same order as requested.
        ProductCatalog title55 = documents.get(0).getItem(catalogTable);
        if (title55 != null) {
            logger.info(title55.toString());
        }

        MovieActor sophiesChoice = documents.get(1).getItem(movieActorTable);
        if (sophiesChoice != null) {
            logger.info(sophiesChoice.toString());
        }

        // 3. The getItem() method returns null if the Document object contains no item from DynamoDB.
        MovieActor blueJasmine = documents.get(2).getItem(movieActorTable);
        if (blueJasmine != null) {
            logger.info(blueJasmine.toString());
        }
    }
```

Die DynamoDB-Tabellen enthalten die folgenden Elemente, bevor das Codebeispiel ausgeführt wird.

```
ProductCatalog{id=2, title='Title 55', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
```

Die folgende Ausgabe wird protokolliert. Wenn ein Element angefordert, aber nicht gefunden wird, wird es nicht zurückgegeben, wie es bei der Anfrage für den genannten Film der Fall ist`Blue Jasmine`.

```
ProductCatalog{id=2, title='Title 55', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
```

## Beispiele für `transactWriteItems()`
<a name="ddb-en-client-use-multiop-trans-writeitems"></a>

Der `[transactWriteItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))` akzeptiert bis zu 100 Put-, Aktualisierungs- oder Löschaktionen in einer einzigen atomaren Transaktion über mehrere Tabellen hinweg. Das *Amazon DynamoDB DynamoDB-Entwicklerhandbuch* enthält Einzelheiten zu Einschränkungen und Fehlerbedingungen des [zugrunde liegenden DynamoDB-Servicebetriebs](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems).

### Einfaches Beispiel
<a name="ddb-en-client-use-multiop-trans-writeitems-basic"></a>

Im folgenden Beispiel werden vier Operationen für zwei Tabellen angefordert. Die entsprechenden Modellklassen [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)und [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)wurden bereits gezeigt.

Jede der drei möglichen Operationen — Put, Update und Delete — verwendet einen speziellen Anforderungsparameter, um die Details anzugeben. 

Der Code nach der ersten Kommentarzeile zeigt die einfache Variante der Methode. `addPutItem()` Die Methode akzeptiert ein `[MappedTableResource](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/MappedTableResource.html)` Objekt und die zu setzende Datenobjektinstanz. Die Anweisung nach Kommentarzeile 2 zeigt die Variante, die eine `[TransactPutItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactPutItemEnhancedRequest.html)` Instanz akzeptiert. Mit dieser Variante können Sie der Anfrage weitere Optionen hinzufügen, z. B. einen Bedingungsausdruck. Ein nachfolgendes [Beispiel](#ddb-en-client-use-multiop-trans-writeitems-opcondition) zeigt einen Bedingungsausdruck für eine einzelne Operation.

Nach Kommentarzeile 3 wird ein Aktualisierungsvorgang angefordert. `[TransactUpdateItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactUpdateItemEnhancedRequest.Builder.html)`hat eine `ignoreNulls()` Methode, mit der Sie konfigurieren können, was das SDK mit `null` Werten im Modellobjekt macht. Wenn die `ignoreNulls()` Methode true zurückgibt, entfernt das SDK nicht die Attributwerte der Tabelle für Datenobjektattribute, die `null` Wenn die `ignoreNulls()` Methode false zurückgibt, fordert das SDK den DynamoDB-Dienst auf, die Attribute aus dem Element in der Tabelle zu entfernen. Der Standardwert für `ignoreNulls` ist False.

Die Aussage nach Kommentarzeile 4 zeigt die Variante einer Löschanforderung, die ein Datenobjekt akzeptiert. Der erweiterte Client extrahiert die Schlüsselwerte, bevor er die endgültige Anfrage sendet.

```
    public static void transactWriteItems(DynamoDbEnhancedClient enhancedClient,
                                          DynamoDbTable<ProductCatalog> catalogTable,
                                          DynamoDbTable<MovieActor> movieActorTable) {

        enhancedClient.transactWriteItems(b -> b
                // 1. Simplest variation of put item request.
                .addPutItem(catalogTable, getProductCatId2())
                // 2. Put item request variation that accommodates condition expressions.
                .addPutItem(movieActorTable, TransactPutItemEnhancedRequest.builder(MovieActor.class)
                        .item(getMovieActorStreep())
                        .conditionExpression(Expression.builder().expression("attribute_not_exists (movie)").build())
                        .build())
                // 3. Update request that does not remove attribute values on the table if the data object's value is null.
                .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class)
                        .item(getProductCatId4ForUpdate())
                        .ignoreNulls(Boolean.TRUE)
                        .build())
                // 4. Variation of delete request that accepts a data object. The key values are extracted for the request.
                .addDeleteItem(movieActorTable, getMovieActorBlanchett())
        );
    }
```

Die folgenden Hilfsmethoden stellen die Datenobjekte für die `add*Item` Parameter bereit.

#### Hilfsmethoden
<a name="ddb-en-client-use-multiop-trans-writeitems-basic-helpers"></a>

```
    public static ProductCatalog getProductCatId2() {
        return ProductCatalog.builder()
                .id(2)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(30.22))
                .title("Title 55")
                .build();
    }

    public static ProductCatalog getProductCatId4ForUpdate() {
        return ProductCatalog.builder()
                .id(4)
                .price(BigDecimal.valueOf(40.00))
                .title("Title 1")
                .build();
    }

    public static MovieActor getMovieActorBlanchett() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Cate Blanchett");
        movieActor.setMovieName("Tar");
        movieActor.setActingYear(2022);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("National Institute of Dramatic Art");
        return movieActor;
    }

    public static MovieActor getMovieActorStreep() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Meryl Streep");
        movieActor.setMovieName("Sophie's Choice");
        movieActor.setActingYear(1982);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("Yale School of Drama");
        return movieActor;
    }
```

Die DynamoDB-Tabellen enthalten die folgenden Elemente, bevor das Codebeispiel ausgeführt wird.

```
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
```

Die folgenden Elemente befinden sich in den Tabellen, nachdem die Ausführung des Codes abgeschlossen ist.

```
3 | ProductCatalog{id=2, title='Title 55', isbn='1-565-85698', authors=[a, b], price=30.22}
4 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=40.0}
5 | MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
```

Das Element in Zeile 2 wurde gelöscht und die Zeilen 3 und 5 zeigen die Elemente, die eingefügt wurden. Zeile 4 zeigt die Aktualisierung von Zeile 1. Der `price` Wert ist der einzige Wert, der sich für den Artikel geändert hat. Wenn False zurückgegeben `ignoreNulls()` worden wäre, würde Zeile 4 wie die folgende Zeile aussehen.

```
ProductCatalog{id=4, title='Title 1', isbn='null', authors=null, price=40.0}
```

### Beispiel für eine Zustandsprüfung
<a name="ddb-en-client-use-multiop-trans-writeitems-checkcond"></a>

Das folgende Beispiel zeigt die Verwendung einer Zustandsprüfung. Eine Zustandsprüfung wird verwendet, um zu überprüfen, ob ein Element vorhanden ist, oder um den Zustand bestimmter Attribute eines Elements in der Datenbank zu überprüfen. Der Artikel, der bei der Zustandsprüfung geprüft wurde, kann nicht für einen anderen Vorgang in der Transaktion verwendet werden.

**Anmerkung**  
Sie können nicht in derselben Transaktion mit mehreren Operationen auf das gleiche Element abzielen. Sie können beispielsweise nicht eine Zustandsprüfung durchführen und gleichzeitig versuchen, denselben Artikel in derselben Transaktion zu aktualisieren.

Das Beispiel zeigt einen von jedem Operationstyp in einer transaktionalen Anforderung zum Schreiben von Elementen. Nach Kommentarzeile 2 gibt die `addConditionCheck()` Methode die Bedingung an, dass die Transaktion fehlschlägt, wenn der `conditionExpression` Parameter als 0 ausgewertet wird. `false` Der Bedingungsausdruck, der von der im Block Helper-Methoden gezeigten Methode zurückgegeben wird, prüft, ob das Preisjahr für den Film ungleich `Sophie's Choice` ist. `1982` Ist dies der Fall, wird der Ausdruck als 0 ausgewertet `false` und die Transaktion schlägt fehl.

In diesem Handbuch werden [Ausdrücke](ddb-en-client-expressions.md) in einem anderen Thema ausführlich behandelt.

```
    public static void conditionCheckFailExample(DynamoDbEnhancedClient enhancedClient,
                                                 DynamoDbTable<ProductCatalog> catalogTable,
                                                 DynamoDbTable<MovieActor> movieActorTable) {

        try {
            enhancedClient.transactWriteItems(b -> b
                    // 1. Perform one of each type of operation with the next three methods.
                    .addPutItem(catalogTable, TransactPutItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId2()).build())
                    .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId4ForUpdate())
                            .ignoreNulls(Boolean.TRUE).build())
                    .addDeleteItem(movieActorTable, TransactDeleteItemEnhancedRequest.builder()
                            .key(b1 -> b1
                                    .partitionValue(getMovieActorBlanchett().getMovieName())
                                    .sortValue(getMovieActorBlanchett().getActorName())).build())
                    // 2. Add a condition check on a table item that is not involved in another operation in this request.
                    .addConditionCheck(movieActorTable, ConditionCheck.builder()
                            .conditionExpression(buildConditionCheckExpression())
                            .key(k -> k
                                    .partitionValue("Sophie's Choice")
                                    .sortValue("Meryl Streep"))
                            // 3. Specify the request to return existing values from the item if the condition evaluates to true.
                            .returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
                            .build())
                    .build());
        // 4. Catch the exception if the transaction fails and log the information.
        } catch (TransactionCanceledException ex) {
            ex.cancellationReasons().stream().forEach(cancellationReason -> {
                logger.info(cancellationReason.toString());
            });
        }
    }
```

Die folgenden Hilfsmethoden wurden im vorherigen Codebeispiel verwendet.

#### Hilfsmethoden
<a name="ddb-en-client-use-multiop-trans-writeitems-checkcond-helpers"></a>

```
    private static Expression buildConditionCheckExpression() {
        Map<String, AttributeValue> expressionValue = Map.of(
                ":year", numberValue(1982));

        return Expression.builder()
                .expression("actingyear <> :year")
                .expressionValues(expressionValue)
                .build();
    }

    public static ProductCatalog getProductCatId2() {
        return ProductCatalog.builder()
                .id(2)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(30.22))
                .title("Title 55")
                .build();
    }

    public static ProductCatalog getProductCatId4ForUpdate() {
        return ProductCatalog.builder()
                .id(4)
                .price(BigDecimal.valueOf(40.00))
                .title("Title 1")
                .build();
    }

    public static MovieActor getMovieActorBlanchett() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Cate Blanchett");
        movieActor.setMovieName("Blue Jasmine");
        movieActor.setActingYear(2013);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("National Institute of Dramatic Art");
        return movieActor;
    }
```

Die DynamoDB-Tabellen enthalten die folgenden Elemente, bevor das Codebeispiel ausgeführt wird.

```
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
3 | MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
```

Die folgenden Elemente befinden sich in den Tabellen, nachdem die Ausführung des Codes abgeschlossen ist.

```
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
```

Die Elemente in den Tabellen bleiben unverändert, da die Transaktion fehlgeschlagen ist. Der `actingYear` Wert für den Film `Sophie's Choice` entspricht dem Wert`1982`, der in Zeile 2 der Elemente in der Tabelle vor dem Aufruf der `transactWriteItem()` Methode angegeben wurde.

Um die Stornierungsinformationen für die Transaktion zu erfassen, schließen Sie den `transactWriteItems()` Methodenaufruf in einen `try` Block ein und fügen Sie `catch` den [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/TransactionCanceledException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/TransactionCanceledException.html). Nach Kommentarzeile 4 des Beispiels protokolliert der Code jedes `[CancellationReason](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CancellationReason.html)` Objekt. Da der Code nach der dritten Kommentarzeile des Beispiels angibt, dass Werte für das Element zurückgegeben werden sollen, das zum Fehlschlagen der Transaktion geführt hat, zeigt das Protokoll die unformatierten Datenbankwerte für das `Sophie's Choice` Filmelement an.

```
CancellationReason(Code=None)
CancellationReason(Code=None)
CancellationReason(Code=None)
CancellationReason(Item={actor=AttributeValue(S=Meryl Streep), movie=AttributeValue(S=Sophie's Choice), actingaward=AttributeValue(S=Best Actress), actingyear=AttributeValue(N=1982), actingschoolname=AttributeValue(S=Yale School of Drama)}, ¬
    Code=ConditionalCheckFailed, Message=The conditional request failed.)
```

### Beispiel für eine einzelne Betriebsbedingung
<a name="ddb-en-client-use-multiop-trans-writeitems-opcondition"></a>

Das folgende Beispiel zeigt die Verwendung einer Bedingung für eine einzelne Operation in einer Transaktionsanforderung. Der Löschvorgang nach der ersten Kommentarzeile enthält eine Bedingung, die den Wert des Zielelements der Operation mit der Datenbank vergleicht. In diesem Beispiel gibt der Bedingungsausdruck, der mit der Hilfsmethode nach Kommentarzeile 2 erstellt wurde, an, dass das Element aus der Datenbank gelöscht werden soll, wenn das Schauspieljahr des Films nicht 2013 entspricht.

[Ausdrücke](ddb-en-client-expressions.md) werden später in diesem Handbuch behandelt.

```
    public static void singleOperationConditionFailExample(DynamoDbEnhancedClient enhancedClient,
                                                           DynamoDbTable<ProductCatalog> catalogTable,
                                                           DynamoDbTable<MovieActor> movieActorTable) {
        try {
            enhancedClient.transactWriteItems(b -> b
                    .addPutItem(catalogTable, TransactPutItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId2())
                            .build())
                    .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId4ForUpdate())
                            .ignoreNulls(Boolean.TRUE).build())
                    // 1. Delete operation that contains a condition expression
                    .addDeleteItem(movieActorTable, TransactDeleteItemEnhancedRequest.builder()
                            .key((Key.Builder k) -> {
                                MovieActor blanchett = getMovieActorBlanchett();
                                k.partitionValue(blanchett.getMovieName())
                                        .sortValue(blanchett.getActorName());
                            })
                            .conditionExpression(buildDeleteItemExpression())
                            .returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
                            .build())
                    .build());
        } catch (TransactionCanceledException ex) {
            ex.cancellationReasons().forEach(cancellationReason -> logger.info(cancellationReason.toString()));
        }
    }

    // 2. Provide condition expression to check if 'actingyear' is not equal to 2013.
    private static Expression buildDeleteItemExpression() {
        Map<String, AttributeValue> expressionValue = Map.of(
                ":year", numberValue(2013));

        return Expression.builder()
                .expression("actingyear <> :year")
                .expressionValues(expressionValue)
                .build();
    }
```

Die folgenden Hilfsmethoden wurden im vorherigen Codebeispiel verwendet.

#### Hilfsmethoden
<a name="ddb-en-client-use-multiop-trans-writeitems-opcondition-helpers"></a>

```
    public static ProductCatalog getProductCatId2() {
        return ProductCatalog.builder()
                .id(2)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(30.22))
                .title("Title 55")
                .build();
    }

    public static ProductCatalog getProductCatId4ForUpdate() {
        return ProductCatalog.builder()
                .id(4)
                .price(BigDecimal.valueOf(40.00))
                .title("Title 1")
                .build();
    }
    public static MovieActor getMovieActorBlanchett() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Cate Blanchett");
        movieActor.setMovieName("Blue Jasmine");
        movieActor.setActingYear(2013);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("National Institute of Dramatic Art");
        return movieActor;
    }
```

Die DynamoDB-Tabellen enthalten die folgenden Elemente, bevor das Codebeispiel ausgeführt wird.

```
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
```

Die folgenden Elemente befinden sich in den Tabellen, nachdem die Ausführung des Codes abgeschlossen ist.

```
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2023-03-15 11:29:07 [main] INFO  org.example.tests.TransactDemoTest:168 - MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
```

Die Elemente in den Tabellen bleiben unverändert, da die Transaktion fehlgeschlagen ist. Der `actingYear` Wert für den Film `Blue Jasmine` entspricht `2013` in Zeile 2 der Elementliste, bevor das Codebeispiel ausgeführt wird.

Die folgenden Zeilen werden in der Konsole protokolliert.

```
CancellationReason(Code=None)
CancellationReason(Code=None)
CancellationReason(Item={actor=AttributeValue(S=Cate Blanchett), movie=AttributeValue(S=Blue Jasmine), actingaward=AttributeValue(S=Best Actress), actingyear=AttributeValue(N=2013), actingschoolname=AttributeValue(S=National Institute of Dramatic Art)}, 
    Code=ConditionalCheckFailed, Message=The conditional request failed)
```

# Verwenden Sie sekundäre Indizes
<a name="ddb-en-client-use-secindex"></a>

Sekundäre Indizes verbessern den Datenzugriff, indem sie alternative Schlüssel definieren, die Sie bei Abfrage- und Scanvorgängen verwenden. Globale Sekundärindizes (GSI) haben einen Partitionsschlüssel und einen Sortierschlüssel, die sich von denen in der Basistabelle unterscheiden können. Im Gegensatz dazu verwenden lokale Sekundärindizes (LSI) den Partitionsschlüssel des Primärindexes.

## Kommentieren Sie die Datenklasse mit Anmerkungen zum sekundären Index
<a name="ddb-en-client-use-secindex-annomodel"></a>

Für Attribute, die an sekundären Indizes beteiligt sind, ist entweder die `@DynamoDbSecondarySortKey` Anmerkung `@DynamoDbSecondaryPartitionKey` oder erforderlich.

Die folgende Klasse zeigt Anmerkungen für zwei Indizes. Die angegebene GSI *SubjectLastPostedDateIndex*verwendet das `Subject` Attribut für den Partitionsschlüssel und das `LastPostedDateTime` für den Sortierschlüssel. Die benannte LSI *ForumLastPostedDateIndex*verwendet den `ForumName` als Partitionsschlüssel und `LastPostedDateTime` als Sortierschlüssel.

Beachten Sie, dass das `Subject` Attribut eine doppelte Rolle spielt. Es ist der Sortierschlüssel des Primärschlüssels und der Partitionsschlüssel der genannten *SubjectLastPostedDateIndex*GSI.

### `MessageThread`-Klasse
<a name="ddb-en-client-use-secindex-class"></a>

Die `MessageThread` Klasse eignet sich als Datenklasse für die [Thread-Beispieltabelle](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AppendixSampleTables.html) im *Amazon DynamoDB Developer Guide*.

#### Importe
<a name="ddb-en-client-use-secindex-classimports"></a>

```
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.util.List;
```

```
@DynamoDbBean
public class MessageThread {
    private String ForumName;
    private String Subject;
    private String Message;
    private String LastPostedBy;
    private String LastPostedDateTime;
    private Integer Views;
    private Integer Replies;
    private Integer Answered;
    private List<String> Tags;

    @DynamoDbPartitionKey
    public String getForumName() {
        return ForumName;
    }

    public void setForumName(String forumName) {
        ForumName = forumName;
    }

    // Sort key for primary index and partition key for GSI "SubjectLastPostedDateIndex".
    @DynamoDbSortKey
    @DynamoDbSecondaryPartitionKey(indexNames = "SubjectLastPostedDateIndex")
    public String getSubject() {
        return Subject;
    }

    public void setSubject(String subject) {
        Subject = subject;
    }

    // Sort key for GSI "SubjectLastPostedDateIndex" and sort key for LSI "ForumLastPostedDateIndex".
    @DynamoDbSecondarySortKey(indexNames = {"SubjectLastPostedDateIndex", "ForumLastPostedDateIndex"})
    public String getLastPostedDateTime() {
        return LastPostedDateTime;
    }

    public void setLastPostedDateTime(String lastPostedDateTime) {
        LastPostedDateTime = lastPostedDateTime;
    }
    public String getMessage() {
        return Message;
    }

    public void setMessage(String message) {
        Message = message;
    }

    public String getLastPostedBy() {
        return LastPostedBy;
    }

    public void setLastPostedBy(String lastPostedBy) {
        LastPostedBy = lastPostedBy;
    }

    public Integer getViews() {
        return Views;
    }

    public void setViews(Integer views) {
        Views = views;
    }

    @DynamoDbSecondaryPartitionKey(indexNames = "ForumRepliesIndex")
    public Integer getReplies() {
        return Replies;
    }

    public void setReplies(Integer replies) {
        Replies = replies;
    }

    public Integer getAnswered() {
        return Answered;
    }

    public void setAnswered(Integer answered) {
        Answered = answered;
    }

    public List<String> getTags() {
        return Tags;
    }

    public void setTags(List<String> tags) {
        Tags = tags;
    }

    public MessageThread() {
        this.Answered = 0;
        this.LastPostedBy = "";
        this.ForumName = "";
        this.Message = "";
        this.LastPostedDateTime = "";
        this.Replies = 0;
        this.Views = 0;
        this.Subject = "";
    }

    @Override
    public String toString() {
        return "MessageThread{" +
                "ForumName='" + ForumName + '\'' +
                ", Subject='" + Subject + '\'' +
                ", Message='" + Message + '\'' +
                ", LastPostedBy='" + LastPostedBy + '\'' +
                ", LastPostedDateTime='" + LastPostedDateTime + '\'' +
                ", Views=" + Views +
                ", Replies=" + Replies +
                ", Answered=" + Answered +
                ", Tags=" + Tags +
                '}';
    }
}
```

## Erstellen Sie den Index
<a name="ddb-en-client-use-secindex-confindex"></a>

Ab Version 2.20.86 des SDK for Java generiert die `createTable()` Methode automatisch Sekundärindizes aus Datenklassenanmerkungen. Standardmäßig werden alle Attribute aus der Basistabelle in einen Index kopiert, und die bereitgestellten Durchsatzwerte betragen 20 Lesekapazitätseinheiten und 20 Schreibkapazitätseinheiten.

Wenn Sie jedoch eine SDK-Version vor 2.20.86 verwenden, müssen Sie den Index zusammen mit der Tabelle erstellen, wie im folgenden Beispiel gezeigt. In diesem Beispiel werden die beiden Indizes für die Tabelle erstellt. `Thread` Der [Builder-Parameter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html) verfügt über Methoden zur Konfiguration beider Indextypen, wie nach den Kommentarzeilen 1 und 2 gezeigt. Sie verwenden die `indexName()` Methode des Indexgenerators, um die in den Datenklassenanmerkungen angegebenen Indexnamen dem gewünschten Indextyp zuzuordnen.

Dieser Code konfiguriert alle Tabellenattribute so, dass sie nach den Kommentarzeilen 3 und 4 in beiden Indizes landen. Weitere Informationen zu [Attributprojektionen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.Projections) finden Sie im *Amazon DynamoDB Developer Guide*.

```
    public static void createMessageThreadTable(DynamoDbTable<MessageThread> messageThreadDynamoDbTable, DynamoDbClient dynamoDbClient) {
        messageThreadDynamoDbTable.createTable(b -> b
                // 1. Generate the GSI.
                .globalSecondaryIndices(gsi -> gsi.indexName("SubjectLastPostedDateIndex")
                        // 3. Populate the GSI with all attributes.
                        .projection(p -> p
                                .projectionType(ProjectionType.ALL))
                )
                // 2. Generate the LSI.
                .localSecondaryIndices(lsi -> lsi.indexName("ForumLastPostedDateIndex")
                        // 4. Populate the LSI with all attributes.
                        .projection(p -> p
                                .projectionType(ProjectionType.ALL))
                )
        );
```

## Abfragen mithilfe eines Indexes
<a name="ddb-en-client-use-secindex-query"></a>

Im folgenden Beispiel wird der lokale sekundäre Index *ForumLastPostedDateIndex* abgefragt.

Nach Kommentarzeile 2 erstellen Sie ein [QueryConditional](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)Objekt, das für den Aufruf der [DynamoDbIndex.query ()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbIndex.html#query(java.util.function.Consumer)) -Methode erforderlich ist. 

Sie erhalten nach Kommentarzeile 3 einen Verweis auf den Index, den Sie abfragen möchten, indem Sie den Namen des Indexes übergeben. Nach Kommentarzeile 4 rufen Sie die `query()` Methode für den Index auf und übergeben das `QueryConditional` Objekt. 

Sie konfigurieren die Abfrage auch so, dass sie drei Attributwerte zurückgibt, wie nach Kommentarzeile 5 gezeigt. Wenn nicht aufgerufen `attributesToProject()` wird, gibt die Abfrage alle Attributwerte zurück. Beachten Sie, dass die angegebenen Attributnamen mit Kleinbuchstaben beginnen. Diese Attributnamen stimmen mit den in der Tabelle verwendeten überein, nicht unbedingt mit den Attributnamen der Datenklasse.

Folgen Sie der Kommentarzeile 6 und wiederholen Sie die Ergebnisse, protokollieren Sie jedes von der Abfrage zurückgegebene Element und speichern Sie es auch in der Liste, um zum Aufrufer zurückzukehren.

```
public class IndexScanExamples {
    private static Logger logger = LoggerFactory.getLogger(IndexScanExamples.class);

    public static List<MessageThread> queryUsingSecondaryIndices(String lastPostedDate,
                                                                 DynamoDbTable<MessageThread> threadTable) {
        // 1. Log the parameter value.
        logger.info("lastPostedDate value: {}", lastPostedDate);

        // 2. Create a QueryConditional whose sort key value must be greater than or equal to the parameter value.
        QueryConditional queryConditional = QueryConditional.sortGreaterThanOrEqualTo(qc ->
                qc.partitionValue("Forum02").sortValue(lastPostedDate));

        // 3. Specify the index name to query.
        final DynamoDbIndex<MessageThread> forumLastPostedDateIndex = threadTable.index("ForumLastPostedDateIndex");

        // 4. Perform the query using the QueryConditional object.
        final SdkIterable<Page<MessageThread>> pagedResult = forumLastPostedDateIndex.query(q -> q
                .queryConditional(queryConditional)
                // 5. Request three attribute in the results.
                .attributesToProject("forumName", "subject", "lastPostedDateTime"));

        List<MessageThread> collectedItems = new ArrayList<>();
        // 6. Iterate through pages response and sort the items.
        pagedResult.stream().forEach(page -> page.items().stream()
                .sorted(Comparator.comparing(MessageThread::getLastPostedDateTime))
                .forEach(mt -> {
                    // 7. Log the returned items and add the collection to return to the caller.
                    logger.info(mt.toString());
                    collectedItems.add(mt);
                }));
        return collectedItems;
    }
```

Die folgenden Elemente sind in der Datenbank vorhanden, bevor die Abfrage ausgeführt wird.

```
MessageThread{ForumName='Forum01', Subject='Subject01', Message='Message01', LastPostedBy='', LastPostedDateTime='2023.03.28', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject02', Message='Message02', LastPostedBy='', LastPostedDateTime='2023.03.29', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject04', Message='Message04', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject08', Message='Message08', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject10', Message='Message10', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject03', Message='Message03', LastPostedBy='', LastPostedDateTime='2023.03.30', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject06', Message='Message06', LastPostedBy='', LastPostedDateTime='2023.04.02', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject09', Message='Message09', LastPostedBy='', LastPostedDateTime='2023.04.05', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum05', Subject='Subject05', Message='Message05', LastPostedBy='', LastPostedDateTime='2023.04.01', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum07', Subject='Subject07', Message='Message07', LastPostedBy='', LastPostedDateTime='2023.04.03', Views=0, Replies=0, Answered=0, Tags=null}
```

Die Protokollierungsanweisungen in den Zeilen 1 und 6 führen zu der folgenden Konsolenausgabe.

```
lastPostedDate value: 2023.03.31
MessageThread{ForumName='Forum02', Subject='Subject04', Message='', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject08', Message='', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject10', Message='', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}
```

Die Abfrage hat Elemente mit dem `forumName` Wert *Forum02* und einem `lastPostedDateTime` Wert größer oder gleich *2023.03.31* zurückgegeben. Die Ergebnisse zeigen `message` Werte mit einer leeren Zeichenfolge, obwohl die `message` Attribute Werte im Index haben. Das liegt daran, dass das Nachrichtenattribut im Code nach Kommentarzeile 5 nicht projiziert wurde. 

# Verwenden Sie erweiterte Mapping-Funktionen
<a name="ddb-en-client-adv-features"></a>

Erfahren Sie mehr über erweiterte Tabellenschemafunktionen in der DynamoDB Enhanced Client API.

## Machen Sie sich mit Tabellenschematypen vertraut
<a name="ddb-en-client-adv-features-schm-overview"></a>

`[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)`ist die Schnittstelle zur Mapping-Funktionalität der DynamoDB Enhanced Client API. Sie kann ein Datenobjekt einer Map von und zu einer Map von zuordnen. [AttributeValues](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html) Ein `TableSchema` Objekt muss die Struktur der Tabelle kennen, die es abbildet. Diese Strukturinformationen werden in einem [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.html)Objekt gespeichert.

Die erweiterte Client-API hat mehrere Implementierungen von`TableSchema`, die im Folgenden aufgeführt sind. 

### Aus kommentierten Klassen generiertes Tabellenschema
<a name="ddb-en-client-adv-features-schema-mapped"></a>

Das Erstellen eines `TableSchema` aus annotierten Klassen ist ein relativ teurer Vorgang. Wir empfehlen daher, dies einmal beim Start der Anwendung zu tun.

 [ BeanTableSchema ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchema.html)   
Diese Implementierung basiert auf Attributen und Anmerkungen einer Bean-Klasse. Ein Beispiel für diesen Ansatz wird im [Abschnitt Erste Schritte](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean) demonstriert.  
Wenn `BeanTableSchema` sich a nicht wie erwartet verhält, aktivieren Sie die Debug-Protokollierung für. `software.amazon.awssdk.enhanced.dynamodb.beans`

[ImmutableTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchema.html)  
Diese Implementierung basiert auf einer unveränderlichen Datenklasse. Dieser Ansatz wird im [Arbeiten Sie mit unveränderlichen Datenklassen](ddb-en-client-use-immut.md) Abschnitt beschrieben.

### Mit einem Builder generiertes Tabellenschema
<a name="ddb-en-client-adv-features-schema-static"></a>

Die folgenden `TableSchema` s werden mithilfe eines Builders aus Code erstellt. Dieser Ansatz ist kostengünstiger als der Ansatz, bei dem annotierte Datenklassen verwendet werden. Der Builder-Ansatz vermeidet die Verwendung von Anmerkungen und erfordert keine JavaBean Benennungsstandards.

[StaticTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchema.html)  
Diese Implementierung wurde für veränderbare Datenklassen entwickelt. Im Abschnitt „Erste Schritte“ dieses Handbuchs wurde gezeigt, wie Sie [`StaticTableSchema`mithilfe eines Builders eine generieren](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-builder).

[StaticImmutableTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticImmutableTableSchema.html)  
Ähnlich wie beim Erstellen eines generieren Sie eine Implementierung dieses Typs`StaticTableSchema`, indem Sie einen [Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticImmutableTableSchema.html) für die `TableSchema` Verwendung mit unveränderlichen Datenklassen verwenden.

### Tabellenschema für Daten ohne festes Schema
<a name="ddb-en-client-adv-features-schema-document"></a>

[DocumentTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.html)  
Im Gegensatz zu anderen Implementierungen von `TableSchema` definieren Sie keine Attribute für eine `DocumentTableSchema` Instanz. Normalerweise geben Sie nur Primärschlüssel und Anbieter von Attributkonvertern an. Eine `EnhancedDocument` Instanz stellt die Attribute bereit, die Sie aus einzelnen Elementen oder aus einer JSON-Zeichenfolge erstellen.

# Fügen Sie Attribute explizit ein oder schließen Sie sie aus
<a name="ddb-en-client-adv-features-inex-attr"></a>

Die DynamoDB Enhanced Client API bietet Anmerkungen, um Datenklassenattribute daran zu hindern, zu Attributen in einer Tabelle zu werden. Mit der API können Sie auch einen Attributnamen verwenden, der sich vom Attributnamen der Datenklasse unterscheidet.

## Attribute ausschließen
<a name="ddb-en-client-adv-features-inex-attr-ex"></a>

Um Attribute zu ignorieren, die keiner DynamoDB-Tabelle zugeordnet werden sollten, markieren Sie das Attribut mit der Anmerkung. `@DynamoDbIgnore`

```
private String internalKey;

@DynamoDbIgnore
public String getInternalKey() { return this.internalKey; }
public void setInternalKey(String internalKey) { this.internalKey = internalKey;}
```

## Attribute einbeziehen
<a name="ddb-en-client-adv-features-inex-attr-in"></a>

Um den Namen eines in der DynamoDB-Tabelle verwendeten Attributs zu ändern, markieren Sie es mit der `@DynamoDbAttribute` Anmerkung und geben Sie einen anderen Namen ein.

```
private String internalKey;

@DynamoDbAttribute("renamedInternalKey")
public String getInternalKey() { return this.internalKey; }
public void setInternalKey(String internalKey) { this.internalKey = internalKey;}
```

# Steuern Sie die Attributkonvertierung
<a name="ddb-en-client-adv-features-conversion"></a>

Standardmäßig stellt ein Tabellenschema über eine Standardimplementierung der `[AttributeConverterProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverterProvider.html)` Schnittstelle Konverter für viele gängige Java-Typen bereit. Das allgemeine Standardverhalten lässt sich durch eine benutzerdefinierte `AttributeConverterProvider`-Implementierung ändern. Ebenso können Sie den Konverter für ein einzelnes Attribut anpassen.

Eine Liste der verfügbaren Konverter finden Sie im Java-Dokument zur [AttributeConverter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html)Schnittstelle.

## Stellen Sie Anbieter für benutzerdefinierte Attributkonverter bereit
<a name="ddb-en-client-adv-features-conversion-prov"></a>

Sie können über die `@DynamoDbBean` `(converterProviders = {…})` Anmerkung ein einzelnes `AttributeConverterProvider` oder eine Kette von bestellten `AttributeConverterProvider` S angeben. Jeder benutzerdefinierte `AttributeConverterProvider` Benutzer muss die `AttributeConverterProvider` Schnittstelle erweitern.

Beachten Sie, dass Sie, wenn Sie Ihre eigene Kette von Anbietern für Attributkonverter angeben, den Standardkonverter-Anbieter außer Kraft setzen`DefaultAttributeConverterProvider`. Wenn Sie die Funktionalität von verwenden möchten`DefaultAttributeConverterProvider`, müssen Sie sie in die Kette aufnehmen. 

Es ist auch möglich, die Bean mit einem leeren Array `{}` zu annotieren. Dadurch wird die Verwendung aller Anbieter für Attributkonverter deaktiviert, einschließlich der Standardanbieter. In diesem Fall müssen alle Attribute, die zugeordnet werden sollen, über einen eigenen Attributkonverter verfügen.

Der folgende Ausschnitt zeigt einen einzelnen Konverter-Anbieter.

```
@DynamoDbBean(converterProviders = ConverterProvider1.class)
public class Customer {

}
```

Der folgende Ausschnitt zeigt die Verwendung einer Kette von Konverteranbietern. Da der SDK-Standard zuletzt bereitgestellt wird, hat er die niedrigste Priorität.

```
@DynamoDbBean(converterProviders = {
   ConverterProvider1.class, 
   ConverterProvider2.class,
   DefaultAttributeConverterProvider.class})
public class Customer {

}
```

Die Schema-Builder für statische Tabellen verfügen über eine `attributeConverterProviders()` Methode, die auf die gleiche Weise funktioniert. Dies wird im folgenden Ausschnitt gezeigt.

```
private static final StaticTableSchema<Customer> CUSTOMER_TABLE_SCHEMA =
  StaticTableSchema.builder(Customer.class)
    .newItemSupplier(Customer::new)
    .addAttribute(String.class, a -> a.name("name")
                                     a.getter(Customer::getName)
                                     a.setter(Customer::setName))
    .attributeConverterProviders(converterProvider1, converterProvider2)
    .build();
```

## Überschreiben Sie die Zuordnung eines einzelnen Attributs
<a name="ddb-en-client-adv-features-conversion-single"></a>

Um die Art und Weise, wie ein einzelnes Attribut zugeordnet wird, zu überschreiben, geben Sie an `AttributeConverter` für das Attribut ein. Dieser Zusatz hat Vorrang vor allen Konvertern, die von `AttributeConverterProviders` im Tabellenschema bereitgestellt werden. Dadurch wird ein benutzerdefinierter Konverter nur für dieses Attribut hinzugefügt. Andere Attribute, auch solche desselben Typs, verwenden diesen Konverter nur, wenn er explizit für diese anderen Attribute angegeben ist.

Die `@DynamoDbConvertedBy` Anmerkung wird verwendet, um die benutzerdefinierte `AttributeConverter` Klasse anzugeben, wie im folgenden Codeausschnitt gezeigt.

```
@DynamoDbBean
public class Customer {
    private String name;

    @DynamoDbConvertedBy(CustomAttributeConverter.class)
    public String getName() { return this.name; }
    public void setName(String name) { this.name = name;}
}
```

Die Builder für statische Schemas verfügen über eine entsprechende Methode zur Erstellung von Attributen. `attributeConverter()` Diese Methode benötigt eine Instanz von a, `AttributeConverter` wie im Folgenden gezeigt.

```
private static final StaticTableSchema<Customer> CUSTOMER_TABLE_SCHEMA =
  StaticTableSchema.builder(Customer.class)
    .newItemSupplier(Customer::new)
    .addAttribute(String.class, a -> a.name("name")
                                     a.getter(Customer::getName)
                                     a.setter(Customer::setName)
                                     a.attributeConverter(customAttributeConverter))
    .build();
```

## Beispiel
<a name="ddb-en-client-adv-features-conversion-example"></a>

Dieses Beispiel zeigt eine `AttributeConverterProvider` Implementierung, die einen Attributkonverter für [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/HttpCookie.html](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/HttpCookie.html)Objekte bereitstellt. 

Die folgende `SimpleUser` Klasse enthält ein Attribut mit dem Namen`lastUsedCookie`, das eine Instanz von ist`HttpCookie`.

Der Parameter für die `@DynamoDbBean` Anmerkungen listet die beiden `AttributeConverterProvider` Klassen auf, die Konverter bereitstellen.

------
#### [ Class with annotations ]

```
    @DynamoDbBean(converterProviders = {CookieConverterProvider.class, DefaultAttributeConverterProvider.class})
    public static final class SimpleUser {
        private String name;
        private HttpCookie lastUsedCookie;

        @DynamoDbPartitionKey
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public HttpCookie getLastUsedCookie() {
            return lastUsedCookie;
        }

        public void setLastUsedCookie(HttpCookie lastUsedCookie) {
            this.lastUsedCookie = lastUsedCookie;
        }
```

------
#### [ Static table schema ]

```
    private static final TableSchema<SimpleUser> SIMPLE_USER_TABLE_SCHEMA =
            TableSchema.builder(SimpleUser.class)
                    .newItemSupplier(SimpleUser::new)
                    .attributeConverterProviders(CookieConverterProvider.create(), AttributeConverterProvider.defaultProvider())
                    .addAttribute(String.class, a -> a.name("name")
                            .setter(SimpleUser::setName)
                            .getter(SimpleUser::getName)
                            .tags(StaticAttributeTags.primaryPartitionKey()))
                    .addAttribute(HttpCookie.class, a -> a.name("lastUsedCookie")
                            .setter(SimpleUser::setLastUsedCookie)
                            .getter(SimpleUser::getLastUsedCookie))
                    .build();
```

------

Das `CookieConverterProvider` folgende Beispiel bietet eine Instanz `HttpCookeConverter` von.

```
    public static final class CookieConverterProvider implements AttributeConverterProvider {
        private final Map<EnhancedType<?>, AttributeConverter<?>> converterCache = ImmutableMap.of(
                // 1. Add HttpCookieConverter to the internal cache.
                EnhancedType.of(HttpCookie.class), new HttpCookieConverter());

        public static CookieConverterProvider create() {
            return new CookieConverterProvider();
        }

        // The SDK calls this method to find out if the provider contains a AttributeConverter instance
        // for the EnhancedType<T> argument.
        @SuppressWarnings("unchecked")
        @Override
        public <T> AttributeConverter<T> converterFor(EnhancedType<T> enhancedType) {
            return (AttributeConverter<T>) converterCache.get(enhancedType);
        }
    }
```

### Konvertierungscode
<a name="ddb-en-client-adv-features-conversion-example-code"></a>

In der `transformFrom()` Methode der folgenden `HttpCookieConverter` Klasse empfängt der Code eine `HttpCookie` Instanz und wandelt sie in eine DynamoDB-Map um, die als Attribut gespeichert wird.

Die `transformTo()` Methode empfängt einen DynamoDB-Zuordnungsparameter und ruft dann den `HttpCookie` Konstruktor auf, der einen Namen und einen Wert benötigt.

```
    public static final class HttpCookieConverter implements AttributeConverter<HttpCookie> {

        @Override
        public AttributeValue transformFrom(HttpCookie httpCookie) {

            return AttributeValue.fromM(
            Map.of ("cookieName", AttributeValue.fromS(httpCookie.getName()),
                    "cookieValue", AttributeValue.fromS(httpCookie.getValue()))
            );
        }

        @Override
        public HttpCookie transformTo(AttributeValue attributeValue) {
            Map<String, AttributeValue> map = attributeValue.m();
            return new HttpCookie(
                    map.get("cookieName").s(),
                    map.get("cookieValue").s());
        }

        @Override
        public EnhancedType<HttpCookie> type() {
            return EnhancedType.of(HttpCookie.class);
        }

        @Override
        public AttributeValueType attributeValueType() {
            return AttributeValueType.M;
        }
    }
```

# Ändern Sie das Aktualisierungsverhalten von Attributen
<a name="ddb-en-client-adv-features-upd-behavior"></a>

Sie können das Aktualisierungsverhalten einzelner Attribute anpassen, wenn Sie einen *Aktualisierungsvorgang* durchführen. [Einige Beispiele für Aktualisierungsvorgänge in der DynamoDB Enhanced Client API sind [updateItem () und ()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#updateItem(T)). transactWriteItems](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))

Stellen Sie sich zum Beispiel vor, Sie möchten einen *am erstellten* Zeitstempel in Ihrem Datensatz speichern. Sie möchten jedoch, dass sein Wert nur geschrieben wird, wenn für das Attribut noch kein Wert in der Datenbank vorhanden ist. In diesem Fall verwenden Sie das `[WRITE\$1IF\$1NOT\$1EXISTS](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html#WRITE_IF_NOT_EXISTS)` Aktualisierungsverhalten.

Das folgende Beispiel zeigt die Anmerkung, die dem `createdOn` Attribut das Verhalten hinzufügt.

```
@DynamoDbBean
public class Customer extends GenericRecord {
    private String id;
    private Instant createdOn;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }
    public void setId(String id) { this.name = id; }

    @DynamoDbUpdateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)
    public Instant getCreatedOn() { return this.createdOn; }    
    public void setCreatedOn(Instant createdOn) { this.createdOn = createdOn; }
}
```

Sie können dasselbe Aktualisierungsverhalten deklarieren, wenn Sie ein statisches Tabellenschema erstellen, wie im folgenden Beispiel nach Kommentarzeile 1 gezeigt.

```
static final TableSchema<Customer> CUSTOMER_TABLE_SCHEMA =
     TableSchema.builder(Customer.class)
       .newItemSupplier(Customer::new)
       .addAttribute(String.class, a -> a.name("id")
                                         .getter(Customer::getId)
                                         .setter(Customer::setId)
                                         .tags(StaticAttributeTags.primaryPartitionKey()))
       .addAttribute(Instant.class, a -> a.name("createdOn")
                                          .getter(Customer::getCreatedOn)
                                          .setter(Customer::setCreatedOn)
                                          // 1. Add an UpdateBehavior.
                                          .tags(StaticAttributeTags.updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)))
       .build();
```

# Reduzieren Sie Attribute aus anderen Klassen
<a name="ddb-en-client-adv-features-flatmap"></a>

Wenn die Attribute für Ihre Tabelle entweder durch Vererbung oder Zusammensetzung auf mehrere verschiedene Java-Klassen verteilt sind, bietet die DynamoDB Enhanced Client-API Unterstützung, um die Attribute zu einer Klasse zusammenzufassen.

## Verwenden Sie Vererbung
<a name="ddb-en-client-adv-features-flatmap-inheritance"></a>

Wenn Ihre Klassen Vererbung verwenden, verwenden Sie die folgenden Methoden, um die Hierarchie zu vereinfachen.

### Verwenden Sie Beans mit Anmerkungen
<a name="ddb-en-client-adv-features-flatmap-inheritance-anno"></a>

Für den Annotationsansatz müssen beide Klassen die `@DynamoDbBean` Annotation enthalten und eine Klasse muss eine oder mehrere Primärschlüssel-Annotationen enthalten.

Im Folgenden werden Beispiele für Datenklassen gezeigt, die eine Vererbungsbeziehung haben.

------
#### [ Standard data class ]

```
@DynamoDbBean
public class Customer extends GenericRecord {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

@DynamoDbBean
public abstract class GenericRecord {
    private String id;
    private String createdDate;

    @DynamoDbPartitionKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

Die [`onMethod`Option](https://projectlombok.org/features/experimental/onX) von Lombok kopiert attributbasierte DynamoDB-Anmerkungen, wie z. B., in den generierten Code. `@DynamoDbPartitionKey`

```
@DynamoDbBean
@Data
@ToString(callSuper = true)
public class Customer extends GenericRecord {
    private String name;
}

@Data
@DynamoDbBean
public abstract class GenericRecord {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;
    private String createdDate;
}
```

------

### Verwenden Sie statische Schemas
<a name="ddb-en-client-adv-features-flatmap-inheritance-static"></a>

Verwenden Sie für den statischen Schemaansatz die `extend()` Methode des Builders, um die Attribute der übergeordneten Klasse auf die untergeordnete Klasse zu reduzieren. Dies wird im folgenden Beispiel nach Kommentarzeile 1 gezeigt.

```
        StaticTableSchema<org.example.tests.model.inheritance.stat.GenericRecord> GENERIC_RECORD_SCHEMA =
                StaticTableSchema.builder(org.example.tests.model.inheritance.stat.GenericRecord.class)
                        // The partition key will be inherited by the top level mapper.
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(org.example.tests.model.inheritance.stat.GenericRecord::getId)
                                .setter(org.example.tests.model.inheritance.stat.GenericRecord::setId)
                                .tags(primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("created_date")
                                .getter(org.example.tests.model.inheritance.stat.GenericRecord::getCreatedDate)
                                .setter(org.example.tests.model.inheritance.stat.GenericRecord::setCreatedDate))
                        .build();

        StaticTableSchema<org.example.tests.model.inheritance.stat.Customer> CUSTOMER_SCHEMA =
                StaticTableSchema.builder(org.example.tests.model.inheritance.stat.Customer.class)
                        .newItemSupplier(org.example.tests.model.inheritance.stat.Customer::new)
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(org.example.tests.model.inheritance.stat.Customer::getName)
                                .setter(org.example.tests.model.inheritance.stat.Customer::setName))
                        // 1. Use the extend() method to collapse the parent attributes onto the child class.
                        .extend(GENERIC_RECORD_SCHEMA)     // All the attributes of the GenericRecord schema are added to Customer.
                        .build();
```

Das vorherige Beispiel für ein statisches Schema verwendet die folgenden Datenklassen. Da die Zuordnung beim Erstellen des statischen Tabellenschemas definiert wird, benötigen die Datenklassen keine Anmerkungen.

#### Datenklassen
<a name="gunk"></a>

------
#### [ Standard data class ]

```
public class Customer extends GenericRecord {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}


public abstract class GenericRecord {
    private String id;
    private String createdDate;

    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
```

------
#### [ Lombok ]

```
@Data
@ToString(callSuper = true)
public class Customer extends GenericRecord{
    private String name;
}

@Data
public abstract class GenericRecord {
    private String id;
    private String createdDate;
}
```

------

## Verwenden Sie Zusammensetzung
<a name="ddb-en-client-adv-features-flatmap-comp"></a>

Wenn in Ihren Klassen Komposition verwendet wird, verwenden Sie die folgenden Methoden, um die Hierarchie zu vereinfachen.

### Verwenden Sie Beans mit Anmerkungen
<a name="ddb-en-client-adv-features-flatmap-comp-anno"></a>

Die `@DynamoDbFlatten` Anmerkung reduziert die enthaltene Klasse.

In den folgenden Beispielen für Datenklassen wird die `@DynamoDbFlatten` Anmerkung verwendet, um der Klasse effektiv alle Attribute der enthaltenen `GenericRecord` Klasse hinzuzufügen. `Customer`

------
#### [ Standard data class ]

```
@DynamoDbBean
public class Customer {
    private String name;
    private GenericRecord record;

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    @DynamoDbFlatten
    public GenericRecord getRecord() { return this.record; }
    public void setRecord(GenericRecord record) { this.record = record; }

@DynamoDbBean
public class GenericRecord {
    private String id;
    private String createdDate;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return this.createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

```
@Data
@DynamoDbBean
public class Customer {
    private String name;
    @Getter(onMethod_=@DynamoDbFlatten)
    private GenericRecord record;
}

@Data
@DynamoDbBean
public class GenericRecord {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;
    private String createdDate;
}
```

------

Sie können die Annotation Flatten verwenden, um so viele verschiedene geeignete Klassen wie nötig zu reduzieren. Die folgenden Einschränkungen gelten:
+ Alle Attributnamen müssen eindeutig sein, nachdem sie reduziert wurden.
+ Es darf nie mehr als einen Partitionsschlüssel, Sortierschlüssel oder Tabellennamen geben.

### Verwenden Sie statische Schemas
<a name="ddb-en-client-adv-features-flatmap-comp-static"></a>

Wenn Sie ein statisches Tabellenschema erstellen, verwenden Sie die `flatten()` Methode des Builders. Sie stellen auch die Getter- und Setter-Methoden bereit, die die enthaltene Klasse identifizieren.

```
        StaticTableSchema<GenericRecord> GENERIC_RECORD_SCHEMA =
                StaticTableSchema.builder(GenericRecord.class)
                        .newItemSupplier(GenericRecord::new)
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(GenericRecord::getId)
                                .setter(GenericRecord::setId)
                                .tags(primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("created_date")
                                .getter(GenericRecord::getCreatedDate)
                                .setter(GenericRecord::setCreatedDate))
                        .build();

        StaticTableSchema<Customer> CUSTOMER_SCHEMA =
                StaticTableSchema.builder(Customer.class)
                        .newItemSupplier(Customer::new)
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(Customer::getName)
                                .setter(Customer::setName))
                        // Because we are flattening a component object, we supply a getter and setter so the
                        // mapper knows how to access it.
                        .flatten(GENERIC_RECORD_SCHEMA, Customer::getRecord, Customer::setRecord)
                        .build();
```

Das vorherige Beispiel für ein statisches Schema verwendet die folgenden Datenklassen.

#### Datenklassen
<a name="ddb-en-client-adv-features-flatmap-comp-static-supporting"></a>

------
#### [ Standard data class ]

```
public class Customer {
    private String name;
    private GenericRecord record;

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    public GenericRecord getRecord() { return this.record; }
    public void setRecord(GenericRecord record) { this.record = record; }

public class GenericRecord {
    private String id;
    private String createdDate;

    public String getId() { return this.id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return this.createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

```
@Data
public class Customer {
    private String name;
    private GenericRecord record;
}

@Data
public class GenericRecord {
    private String id;
    private String createdDate;
}
```

------

Sie können das Builder-Muster verwenden, um so viele verschiedene in Frage kommende Klassen zu reduzieren, wie Sie möchten.

## Implikationen für anderen Code
<a name="ddb-en-client-adv-features-flatmap-compare"></a>

Wenn Sie das `@DynamoDbFlatten` Attribut (oder die `flatten()` Builder-Methode) verwenden, enthält das Element in DynamoDB ein Attribut für jedes Attribut des erstellten Objekts. Es enthält auch die Attribute des zusammengesetzten Objekts. 

Wenn Sie dagegen eine Datenklasse mit einer zusammengesetzten Klasse annotieren und diese nicht verwenden`@DynamoDbFlatten`, wird das Element zusammen mit dem zusammengesetzten Objekt als einzelnes Attribut gespeichert.

Vergleichen Sie beispielsweise die im [Beispiel „Reduzieren mit Komposition“ gezeigte `Customer` Klasse mit](#ddb-en-client-adv-features-flatmap-comp-anno) und ohne Reduzierung des Attributs. `record` Sie können den Unterschied mit JSON visualisieren, wie in der folgenden Tabelle dargestellt.


****  

| Mit Abflachen | Ohne Abflachen | 
| --- | --- | 
| 3 Attribute | 2 Attribute | 
|  <pre>{<br />  "id": "1",<br />  "createdDate": "today",<br />  "name": "my name"<br />}</pre>  |  <pre>{<br />  "id": "1",<br />  "record": {<br />      "createdDate": "today",<br />      "name": "my name"<br />  }<br />}</pre>  | 

Der Unterschied wird wichtig, wenn Sie anderen Code haben, der auf die DynamoDB-Tabelle zugreift und erwartet, bestimmte Attribute zu finden.

# Arbeiten Sie mit Attributen wie Beans, Maps, Listen und Sets
<a name="ddb-en-client-adv-features-nested"></a>

Eine Bean-Definition, wie die unten gezeigte `Person` Klasse, könnte Eigenschaften (oder Attribute) definieren, die sich auf Typen mit zusätzlichen Attributen beziehen. In der `Person` Klasse `mainAddress` handelt es sich beispielsweise um eine Eigenschaft, die sich auf ein `Address` Bean bezieht, das zusätzliche Wertattribute definiert. `addresses`bezieht sich auf eine Java-Map, deren Elemente sich auf `Address` Beans beziehen. Diese komplexen Typen können als Container mit einfachen Attributen betrachtet werden, die Sie für ihren Datenwert im Kontext von DynamoDB verwenden. 

*DynamoDB bezeichnet die Werteigenschaften verschachtelter Elemente wie Maps, Listen oder Beans als verschachtelte Attribute.* Im [Amazon DynamoDB Developer Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) wird die gespeicherte Form einer Java-Map, -Liste oder -Bean als *Dokumenttyp* bezeichnet. Einfache Attribute, die Sie in Java für ihren Datenwert verwenden, werden in DynamoDB als *skalare Typen* bezeichnet. *Mengen, die mehrere skalare Elemente desselben Typs enthalten und als Mengentypen bezeichnet werden.* 

Es ist wichtig zu wissen, dass die DynamoDB Enhanced Client-API eine Eigenschaft, die Bean ist, beim Speichern in einen DynamoDB-Kartendokumenttyp konvertiert.

## `Person`-Klasse
<a name="ddb-en-client-adv-features-nested-person"></a>

```
@DynamoDbBean
public class Person {
    private Integer id;
    private String firstName;
    private String lastName;
    private Integer age;
    private Address mainAddress;
    private Map<String, Address> addresses;
    private List<PhoneNumber> phoneNumbers;
    private Set<String> hobbies;

    @DynamoDbPartitionKey
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Address getMainAddress() {
        return mainAddress;
    }

    public void setMainAddress(Address mainAddress) {
        this.mainAddress = mainAddress;
    }

    public Map<String, Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(Map<String, Address> addresses) {
        this.addresses = addresses;
    }

    public List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }

    public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }

    public Set<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(Set<String> hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public String toString() {
        return "Person{" +
               "addresses=" + addresses +
               ", id=" + id +
               ", firstName='" + firstName + '\'' +
               ", lastName='" + lastName + '\'' +
               ", age=" + age +
               ", mainAddress=" + mainAddress +
               ", phoneNumbers=" + phoneNumbers +
               ", hobbies=" + hobbies +
               '}';
    }
}
```

## `Address`-Klasse
<a name="ddb-en-client-adv-features-nested-address"></a>

```
@DynamoDbBean
public class Address {
    private String street;
    private String city;
    private String state;
    private String zipCode;

    public Address() {
    }

    public String getStreet() {
        return this.street;
    }

    public String getCity() {
        return this.city;
    }

    public String getState() {
        return this.state;
    }

    public String getZipCode() {
        return this.zipCode;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public void setState(String state) {
        this.state = state;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return Objects.equals(street, address.street) && Objects.equals(city, address.city) && Objects.equals(state, address.state) && Objects.equals(zipCode, address.zipCode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(street, city, state, zipCode);
    }

    @Override
    public String toString() {
        return "Address{" +
                "street='" + street + '\'' +
                ", city='" + city + '\'' +
                ", state='" + state + '\'' +
                ", zipCode='" + zipCode + '\'' +
                '}';
    }
}
```

## `PhoneNumber`-Klasse
<a name="ddb-en-client-adv-features-nested-phonenumber"></a>

```
@DynamoDbBean
public class PhoneNumber {
    String type;
    String number;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "PhoneNumber{" +
                "type='" + type + '\'' +
                ", number='" + number + '\'' +
                '}';
    }
}
```

## Speichern Sie komplexe Typen
<a name="ddb-en-client-adv-features-nested-mapping"></a>

### Verwenden Sie annotierte Datenklassen
<a name="ddb-en-client-adv-features-nested-map-anno"></a>

Sie speichern verschachtelte Attribute für benutzerdefinierte Klassen, indem Sie sie einfach mit Anmerkungen versehen. Die `Address` Klasse und die `PhoneNumber` Klasse, die zuvor gezeigt wurden, sind nur mit der Anmerkung annotiert. `@DynamoDbBean` Wenn die DynamoDB Enhanced Client-API das Tabellenschema für die `Person` Klasse mit dem folgenden Codeausschnitt erstellt, erkennt die API die Verwendung der `PhoneNumber` Klassen `Address` und und erstellt die entsprechenden Mappings für die Arbeit mit DynamoDB.

```
TableSchema<Person> personTableSchema = TableSchema.fromBean(Person.class);
```

### Verwenden Sie abstrakte Schemas mit Buildern
<a name="ddb-en-client-adv-features-nested-map-builder"></a>

Der alternative Ansatz besteht darin, Schema-Builder für statische Tabellen für jede verschachtelte Bean-Klasse zu verwenden, wie im folgenden Code gezeigt.

Die Tabellenschemas für die `PhoneNumber` Klassen `Address` und sind abstrakt in dem Sinne, dass sie nicht mit einer DynamoDB-Tabelle verwendet werden können. Das liegt daran, dass ihnen Definitionen für den Primärschlüssel fehlen. Sie werden jedoch als verschachtelte Schemas im Tabellenschema für die `Person` Klasse verwendet.

Nach den Kommentarzeilen 1 und 2 in der Definition von sehen Sie den Code`PERSON_TABLE_SCHEMA`, der die abstrakten Tabellenschemas verwendet. Die Verwendung von `documentOf` in der `EnhanceType.documentOf(...)` Methode bedeutet nicht, dass die Methode einen `EnhancedDocument` Typ der Enhanced Document API zurückgibt. Die `documentOf(...)` Methode gibt in diesem Kontext ein Objekt zurück, das weiß, wie es sein Klassenargument mithilfe des Tabellenschema-Arguments DynamoDB-Tabellenattributen zuordnen kann.

#### Statischer Schemacode
<a name="ddb-en-client-adv-features-nested-map-builder-code"></a>

```
    // Abstract table schema that cannot be used to work with a DynamoDB table,
    // but can be used as a nested schema.
    public static final TableSchema<Address> TABLE_SCHEMA_ADDRESS = TableSchema.builder(Address.class)
        .newItemSupplier(Address::new)
        .addAttribute(String.class, a -> a.name("street")
            .getter(Address::getStreet)
            .setter(Address::setStreet))
        .addAttribute(String.class, a -> a.name("city")
            .getter(Address::getCity)
            .setter(Address::setCity))
        .addAttribute(String.class, a -> a.name("zipcode")
            .getter(Address::getZipCode)
            .setter(Address::setZipCode))
        .addAttribute(String.class, a -> a.name("state")
            .getter(Address::getState)
            .setter(Address::setState))
        .build();

    // Abstract table schema that cannot be used to work with a DynamoDB table,
    // but can be used as a nested schema.
    public static final TableSchema<PhoneNumber> TABLE_SCHEMA_PHONENUMBER = TableSchema.builder(PhoneNumber.class)
        .newItemSupplier(PhoneNumber::new)
        .addAttribute(String.class, a -> a.name("type")
            .getter(PhoneNumber::getType)
            .setter(PhoneNumber::setType))
        .addAttribute(String.class, a -> a.name("number")
            .getter(PhoneNumber::getNumber)
            .setter(PhoneNumber::setNumber))
        .build();

    // A static table schema that can be used with a DynamoDB table.
    // The table schema contains two nested schemas that are used to perform mapping to/from DynamoDB.
    public static final TableSchema<Person> PERSON_TABLE_SCHEMA =
        TableSchema.builder(Person.class)
            .newItemSupplier(Person::new)
            .addAttribute(Integer.class, a -> a.name("id")
                .getter(Person::getId)
                .setter(Person::setId)
                .addTag(StaticAttributeTags.primaryPartitionKey()))
            .addAttribute(String.class, a -> a.name("firstName")
                .getter(Person::getFirstName)
                .setter(Person::setFirstName))
            .addAttribute(String.class, a -> a.name("lastName")
                .getter(Person::getLastName)
                .setter(Person::setLastName))
            .addAttribute(Integer.class, a -> a.name("age")
                .getter(Person::getAge)
                .setter(Person::setAge))
            .addAttribute(EnhancedType.documentOf(Address.class, TABLE_SCHEMA_ADDRESS), a -> a.name("mainAddress")
                .getter(Person::getMainAddress)
                .setter(Person::setMainAddress))
            .addAttribute(EnhancedType.listOf(String.class), a -> a.name("hobbies")
                .getter(Person::getHobbies)
                .setter(Person::setHobbies))
            .addAttribute(EnhancedType.mapOf(
                EnhancedType.of(String.class),
                // 1. Use mapping functionality of the Address table schema.
                EnhancedType.documentOf(Address.class, TABLE_SCHEMA_ADDRESS)), a -> a.name("addresses")
                .getter(Person::getAddresses)
                .setter(Person::setAddresses))
            .addAttribute(EnhancedType.listOf(
                // 2. Use mapping functionality of the PhoneNumber table schema.
                EnhancedType.documentOf(PhoneNumber.class, TABLE_SCHEMA_PHONENUMBER)), a -> a.name("phoneNumbers")
                .getter(Person::getPhoneNumbers)
                .setter(Person::setPhoneNumbers))
            .build();
```

## Projektattribute komplexer Typen
<a name="ddb-en-client-adv-features-nested-projection"></a>

Für `query()` und `scan()` Methoden können Sie mithilfe von Methodenaufrufen wie `addNestedAttributeToProject()` und angeben, welche Attribute in den Ergebnissen zurückgegeben werden sollen`attributesToProject()`. Die DynamoDB Enhanced Client API konvertiert die Parameter des Java-Methodenaufrufs in [Projektionsausdrücke](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html), bevor die Anforderung gesendet wird.

Das folgende Beispiel füllt die `Person` Tabelle mit zwei Elementen und führt dann drei Scanvorgänge durch. 

Beim ersten Scan werden alle Elemente in der Tabelle abgerufen, um die Ergebnisse mit den anderen Scanvorgängen zu vergleichen. 

Der zweite Scan verwendet die [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#addNestedAttributeToProject(software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#addNestedAttributeToProject(software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName))Builder-Methode, um nur den `street` Attributwert zurückzugeben.

Der dritte Scanvorgang verwendet die [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#attributesToProject(java.lang.String...)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#attributesToProject(java.lang.String...))Builder-Methode, um die Daten für das Attribut der ersten Ebene zurückzugeben,`hobbies`. Der Attributtyp von `hobbies` ist eine Liste. Um auf einzelne Listenelemente zuzugreifen, führen Sie einen `get()` Vorgang in der Liste aus.

```
        personDynamoDbTable = getDynamoDbEnhancedClient().table("Person", PERSON_TABLE_SCHEMA);
        PersonUtils.createPersonTable(personDynamoDbTable, getDynamoDbClient());
        // Use a utility class to add items to the Person table.
        List<Person> personList = PersonUtils.getItemsForCount(2);
        // This utility method performs a put against DynamoDB to save the instances in the list argument.
        PersonUtils.putCollection(getDynamoDbEnhancedClient(), personList, personDynamoDbTable);

        // The first scan logs all items in the table to compare to the results of the subsequent scans.
        final PageIterable<Person> allItems = personDynamoDbTable.scan();
        allItems.items().forEach(p ->
                // 1. Log what is in the table.
                logger.info(p.toString()));

        // Scan for nested attributes.
        PageIterable<Person> streetScanResult = personDynamoDbTable.scan(b -> b
                // Use the 'addNestedAttributeToProject()' or 'addNestedAttributesToProject()' to access data nested in maps in DynamoDB.
                .addNestedAttributeToProject(
                        NestedAttributeName.create("addresses", "work", "street")
                ));

        streetScanResult.items().forEach(p ->
                //2. Log the results of requesting nested attributes.
                logger.info(p.toString()));

        // Scan for a top-level list attribute.
        PageIterable<Person> hobbiesScanResult = personDynamoDbTable.scan(b -> b
                // Use the 'attributesToProject()' method to access first-level attributes.
                .attributesToProject("hobbies"));

        hobbiesScanResult.items().forEach((p) -> {
            // 3. Log the results of the request for the 'hobbies' attribute.
            logger.info(p.toString());
            // To access an item in a list, first get the parent attribute, 'hobbies', then access items in the list.
            String hobby = p.getHobbies().get(1);
            // 4. Log an item in the list.
            logger.info(hobby);
        });
```

```
// Logged results from comment line 1.
Person{id=2, firstName='first name 2', lastName='last name 2', age=11, addresses={work=Address{street='street 21', city='city 21', state='state 21', zipCode='33333'}, home=Address{street='street 2', city='city 2', state='state 2', zipCode='22222'}}, phoneNumbers=[PhoneNumber{type='home', number='222-222-2222'}, PhoneNumber{type='work', number='333-333-3333'}], hobbies=[hobby 2, hobby 21]}
Person{id=1, firstName='first name 1', lastName='last name 1', age=11, addresses={work=Address{street='street 11', city='city 11', state='state 11', zipCode='22222'}, home=Address{street='street 1', city='city 1', state='state 1', zipCode='11111'}}, phoneNumbers=[PhoneNumber{type='home', number='111-111-1111'}, PhoneNumber{type='work', number='222-222-2222'}], hobbies=[hobby 1, hobby 11]}

// Logged results from comment line 2.
Person{id=null, firstName='null', lastName='null', age=null, addresses={work=Address{street='street 21', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=null}
Person{id=null, firstName='null', lastName='null', age=null, addresses={work=Address{street='street 11', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=null}

// Logged results from comment lines 3 and 4.
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 2, hobby 21]}
hobby 21
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 1, hobby 11]}
hobby 11
```

**Anmerkung**  
Wenn die `attributesToProject()` Methode einer anderen Builder-Methode folgt, die Attribute hinzufügt, die Sie projizieren möchten, `attributesToProject()` ersetzt die mitgelieferte Liste der Attributnamen alle anderen Attributnamen.  
Ein Scan, der mit der `ScanEnhancedRequest` Instanz im folgenden Codeausschnitt durchgeführt wird, gibt nur Hobbydaten zurück.  

```
ScanEnhancedRequest lastOverwrites = ScanEnhancedRequest.builder()
        .addNestedAttributeToProject(
                NestedAttributeName.create("addresses", "work", "street"))
        .addAttributeToProject("firstName")
        // If the 'attributesToProject()' method follows other builder methods that add attributes for projection,
        // its list of attributes replace all previous attributes.
        .attributesToProject("hobbies")
        .build();
PageIterable<Person> hobbiesOnlyResult = personDynamoDbTable.scan(lastOverwrites);
hobbiesOnlyResult.items().forEach(p ->
        logger.info(p.toString()));

// Logged results.
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 2, hobby 21]}
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 1, hobby 11]}
```
Der folgende Codeausschnitt verwendet die Methode zuerst. `attributesToProject()` Bei dieser Reihenfolge werden alle anderen angeforderten Attribute beibehalten.  

```
ScanEnhancedRequest attributesPreserved = ScanEnhancedRequest.builder()
        // Use 'attributesToProject()' first so that the method call does not replace all other attributes
        // that you want to project.
        .attributesToProject("firstName")
        .addNestedAttributeToProject(
                NestedAttributeName.create("addresses", "work", "street"))
        .addAttributeToProject("hobbies")
        .build();
PageIterable<Person> allAttributesResult = personDynamoDbTable.scan(attributesPreserved);
allAttributesResult.items().forEach(p ->
        logger.info(p.toString()));

// Logged results.
Person{id=null, firstName='first name 2', lastName='null', age=null, addresses={work=Address{street='street 21', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=[hobby 2, hobby 21]}
Person{id=null, firstName='first name 1', lastName='null', age=null, addresses={work=Address{street='street 11', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=[hobby 1, hobby 11]}
```

## Verwenden Sie komplexe Typen in Ausdrücken
<a name="ddb-en-client-adv-features-nested-expressions"></a>

Sie können komplexe Typen in Ausdrücken wie Filterausdrücken und Bedingungsausdrücken verwenden, indem Sie Dereferenzierungsoperatoren verwenden, um in der Struktur des komplexen Typs zu navigieren. Verwenden Sie für Objekte und Maps das `. (dot)` und für Listenelemente use `[n]` (eckige Klammern um die Sequenznummer des Elements). Sie können nicht auf einzelne Elemente einer Menge verweisen, aber Sie können die [`contains`Funktion](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) verwenden.

Das folgende Beispiel zeigt zwei Filterausdrücke, die bei Scanvorgängen verwendet werden. Die Filterausdrücke geben die Übereinstimmungsbedingungen für Elemente an, die Sie in den Ergebnissen haben möchten. In dem Beispiel werden `Person` die zuvor gezeigten `PhoneNumber` Klassen`Address`, und verwendet.

```
    public void scanUsingFilterOfNestedAttr() {
        // The following is a filter expression for an attribute that is a map of Address objects.
        // By using this filter expression, the SDK returns Person objects that have an address
        // with 'mailing' as a key and 'MS2' for a state value.
        Expression addressFilter = Expression.builder()
                .expression("addresses.#type.#field = :value")
                .putExpressionName("#type", "mailing")
                .putExpressionName("#field", "state")
                .putExpressionValue(":value", AttributeValue.builder().s("MS2").build())
                .build();

        PageIterable<Person> addressFilterResults = personDynamoDbTable.scan(rb -> rb.
                filterExpression(addressFilter));
        addressFilterResults.items().stream().forEach(p -> logger.info("Person: {}", p));

        assert addressFilterResults.items().stream().count() == 1;


        // The following is a filter expression for an attribute that is a list of phone numbers.
        // By using this filter expression, the SDK returns Person objects whose second phone number
        // in the list has a type equal to 'cell'.
        Expression phoneFilter = Expression.builder()
                .expression("phoneNumbers[1].#type = :type")
                .putExpressionName("#type", "type")
                .putExpressionValue(":type", AttributeValue.builder().s("cell").build())
                .build();

        PageIterable<Person> phoneFilterResults = personDynamoDbTable.scan(rb -> rb
                .filterExpression(phoneFilter)
                .attributesToProject("id", "firstName", "lastName", "phoneNumbers")
        );

        phoneFilterResults.items().stream().forEach(p -> logger.info("Person: {}", p));

        assert phoneFilterResults.items().stream().count() == 1;
        assert phoneFilterResults.items().stream().findFirst().get().getPhoneNumbers().get(1).getType().equals("cell");
    }
```

### Hilfsmethode, die die Tabelle auffüllt
<a name="nested-expressions-helper-method"></a>

```
    public static void populateDatabase() {
        Person person1 = new Person();
        person1.setId(1);
        person1.setFirstName("FirstName1");
        person1.setLastName("LastName1");

        Address billingAddr1 = new Address();
        billingAddr1.setState("BS1");
        billingAddr1.setCity("BillingTown1");

        Address mailing1 = new Address();
        mailing1.setState("MS1");
        mailing1.setCity("MailingTown1");

        person1.setAddresses(Map.of("billing", billingAddr1, "mailing", mailing1));

        PhoneNumber pn1_1 = new PhoneNumber();
        pn1_1.setType("work");
        pn1_1.setNumber("111-111-1111");

        PhoneNumber pn1_2 = new PhoneNumber();
        pn1_2.setType("home");
        pn1_2.setNumber("222-222-2222");

        List<PhoneNumber> phoneNumbers1 = List.of(pn1_1, pn1_2);
        person1.setPhoneNumbers(phoneNumbers1);

        personDynamoDbTable.putItem(person1);

        Person person2 = person1;
        person2.setId(2);
        person2.setFirstName("FirstName2");
        person2.setLastName("LastName2");

        Address billingAddress2 = billingAddr1;
        billingAddress2.setCity("BillingTown2");
        billingAddress2.setState("BS2");

        Address mailing2 = mailing1;
        mailing2.setCity("MailingTown2");
        mailing2.setState("MS2");

        person2.setAddresses(Map.of("billing", billingAddress2, "mailing", mailing2));

        PhoneNumber pn2_1 = new PhoneNumber();
        pn2_1.setType("work");
        pn2_1.setNumber("333-333-3333");

        PhoneNumber pn2_2 = new PhoneNumber();
        pn2_2.setType("cell");
        pn2_2.setNumber("444-444-4444");

        List<PhoneNumber> phoneNumbers2 = List.of(pn2_1, pn2_2);
        person2.setPhoneNumbers(phoneNumbers2);

        personDynamoDbTable.putItem(person2);
    }
```

### JSON-Darstellung von Elementen in der Datenbank
<a name="nested-attributes-expression-json-items"></a>

```
{
 "id": 1,
 "addresses": {
  "billing": {
   "city": "BillingTown1",
   "state": "BS1",
   "street": null,
   "zipCode": null
  },
  "mailing": {
   "city": "MailingTown1",
   "state": "MS1",
   "street": null,
   "zipCode": null
  }
 },
 "firstName": "FirstName1",
 "lastName": "LastName1",
 "phoneNumbers": [
  {
   "number": "111-111-1111",
   "type": "work"
  },
  {
   "number": "222-222-2222",
   "type": "home"
  }
 ]
}

{
 "id": 2,
 "addresses": {
  "billing": {
   "city": "BillingTown2",
   "state": "BS2",
   "street": null,
   "zipCode": null
  },
  "mailing": {
   "city": "MailingTown2",
   "state": "MS2",
   "street": null,
   "zipCode": null
  }
 },
 "firstName": "FirstName2",
 "lastName": "LastName2",
 "phoneNumbers": [
  {
   "number": "333-333-3333",
   "type": "work"
  },
  {
   "number": "444-444-4444",
   "type": "cell"
  }
 ]
}
```

## Aktualisieren Sie Elemente, die komplexe Typen enthalten
<a name="ddb-en-client-adv-features-nested-updates"></a>

Um ein Element zu aktualisieren, das komplexe Typen enthält, haben Sie zwei grundlegende Methoden:
+ Ansatz 1: Rufen Sie zuerst das Element ab (mithilfe von`getItem`), aktualisieren Sie das Objekt und rufen Sie es dann auf`DynamoDbTable#updateItem`.
+ Ansatz 2: Rufen Sie das Element nicht ab, sondern erstellen Sie eine neue Instanz, legen Sie die Eigenschaften fest, die Sie aktualisieren möchten, und leiten Sie die Instanz weiter, `DynamoDbTable#updateItem` indem Sie den entsprechenden Wert von festlegen [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html). Bei diesem Ansatz müssen Sie das Element nicht abrufen, bevor Sie es aktualisieren.

Die in diesem Abschnitt gezeigten Beispiele verwenden die zuvor aufgeführten `PhoneNumber` Klassen `Person``Address`, und.

### Aktualisierungsansatz 1: Abrufen, dann aktualisieren
<a name="ddb-en-client-adv-features-nested-updates-retreive"></a>

Mit diesem Ansatz stellen Sie sicher, dass beim Update keine Daten verloren gehen. Die DynamoDB Enhanced Client API erstellt die Bean mit den Attributen des in DynamoDB gespeicherten Elements neu, einschließlich Werten komplexer Typen. Anschließend müssen Sie die Getter und Setter verwenden, um die Bean zu aktualisieren. Der Nachteil dieses Ansatzes sind die Kosten, die Ihnen entstehen, wenn Sie den Artikel zuerst abrufen.

Das folgende Beispiel zeigt, dass keine Daten verloren gehen, wenn Sie das Element zuerst abrufen, bevor Sie es aktualisieren.

```
    public void retrieveThenUpdateExample()  {
        // Assume that we ran this code yesterday.
        Person person = new Person();
        person.setId(1);
        person.setFirstName("FirstName");
        person.setLastName("LastName");

        Address mainAddress = new Address();
        mainAddress.setStreet("123 MyStreet");
        mainAddress.setCity("MyCity");
        mainAddress.setState("MyState");
        mainAddress.setZipCode("MyZipCode");
        person.setMainAddress(mainAddress);

        PhoneNumber homePhone = new PhoneNumber();
        homePhone.setNumber("1111111");
        homePhone.setType("HOME");
        person.setPhoneNumbers(List.of(homePhone));

        personDynamoDbTable.putItem(person);

        // Assume that we are running this code now.
        // First, retrieve the item
        Person retrievedPerson = personDynamoDbTable.getItem(Key.builder().partitionValue(1).build());

        // Make any updates.
        retrievedPerson.getMainAddress().setCity("YourCity");

        // Save the updated bean. 'updateItem' returns the bean as it appears after the update.
        Person updatedPerson = personDynamoDbTable.updateItem(retrievedPerson);

        // Verify for this example.
        Address updatedMainAddress = updatedPerson.getMainAddress();
        assert updatedMainAddress.getCity().equals("YourCity");
        assert updatedMainAddress.getState().equals("MyState"); // Unchanged.
        // The list of phone numbers remains; it was not set to null;
        assert updatedPerson.getPhoneNumbers().size() == 1;
    }
```

### Aktualisierungsansatz 2: Verwenden Sie eine `IgnoreNullsMode` Aufzählung, ohne das Element zuerst abzurufen
<a name="ddb-en-client-adv-features-nested-updates-nullmode"></a>

Um ein Element in DynamoDB zu aktualisieren, können Sie ein neues Objekt angeben, das nur die Eigenschaften hat, die Sie aktualisieren möchten, und die anderen Werte auf Null belassen. Bei diesem Ansatz müssen Sie wissen, wie Nullwerte im Objekt vom SDK behandelt werden und wie Sie das Verhalten steuern können.

Um anzugeben, welche Eigenschaften mit Nullwerten das SDK ignorieren soll, geben Sie beim Erstellen des eine `IgnoreNullsMode` Aufzählung an. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/UpdateItemEnhancedRequest.Builder.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/UpdateItemEnhancedRequest.Builder.html) Als Beispiel für die Verwendung eines der Aufzählungswerte verwendet der folgende Codeausschnitt den Modus. `IgnoreNullsMode.SCALAR_ONLY`

```
// Create a new Person object to update the existing item in DynamoDB.
Person personForUpdate = new Person();
personForUpdate.setId(1);
personForUpdate.setFirstName("updatedFirstName");  // 'firstName' is a top scalar property.

Address addressForUpdate = new Address();
addressForUpdate.setCity("updatedCity");
personForUpdate.setMainAddress(addressForUpdate);

personDynamoDbTable.updateItem(r -> r
                .item(personForUpdate)
                .ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY));

/* With IgnoreNullsMode.SCALAR_ONLY provided, The SDK ignores all null properties. The SDK adds or replaces
the 'firstName' property with the provided value, "updatedFirstName". The SDK updates the 'city' value of
'mainAddress', as long as the 'mainAddress' attribute already exists in DynamoDB.

In the background, the SDK generates an update expression that it sends in the request to DynamoDB.
The following JSON object is a simplified version of what it sends. Notice that the SDK includes the paths
to 'mainAddress.city' and 'firstName' in the SET clause of the update expression. No null values in
'personForUpdate' are included.

{
  "TableName": "PersonTable",
  "Key": {
    "id": {
      "N": "1"
    }
  },
  "ReturnValues": "ALL_NEW",
  "UpdateExpression": "SET #mainAddress.#city = :mainAddress_city, #firstName = :firstName",
  "ExpressionAttributeNames": {
    "#city": "city",
    "#firstName": "firstName",
    "#mainAddress": "mainAddress"
  },
  "ExpressionAttributeValues": {
    ":firstName": {
      "S": "updatedFirstName"
    },
    ":mainAddress_city": {
      "S": "updatedCity"
    }
  }
}

Had we chosen 'IgnoreNullsMode.DEFAULT' instead of 'IgnoreNullsMode.SCALAR_ONLY', the SDK would have included
null values in the "ExpressionAttributeValues" section of the request as shown in the following snippet.

  "ExpressionAttributeValues": {
    ":mainAddress": {
      "M": {
        "zipCode": {
          "NULL": true
        },
        "city": {
          "S": "updatedCity"
        },
        "street": {
          "NULL": true
        },
        "state": {
          "NULL": true
        }
      }
    },
    ":firstName": {
      "S": "updatedFirstName"
    }
  }
*/
```

Das Amazon DynamoDB DynamoDB-Entwicklerhandbuch enthält weitere Informationen zu [Aktualisierungsausdrücken](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html).

#### Beschreibungen der Optionen `IgnoreNullsMode`
<a name="ignore-nulls-mode-descriptions"></a>
+ `IgnoreNullsMode.SCALAR_ONLY`- Verwenden Sie diese Einstellung, um skalare Attribute auf jeder Ebene zu aktualisieren. Das SDK erstellt eine Aktualisierungsanweisung, die nur skalare Attribute ungleich Null an DynamoDB sendet. Das SDK ignoriert nullwertige, skalare Attribute einer Bean oder Map und behält den gespeicherten Wert in DynamoDB bei.

  Wenn Sie ein skalares Attribut von map oder bean aktualisieren, muss die Map bereits in DynamoDB vorhanden sein. Wenn Sie dem Objekt eine Map oder eine Bean hinzufügen, die noch nicht für das Objekt in DynamoDB vorhanden ist, erhalten Sie eine `DynamoDbException` mit der Meldung *Der im Aktualisierungsausdruck angegebene Dokumentpfad ist für die Aktualisierung ungültig*. Sie müssen `MAPS_ONLY` den Modus verwenden, um DynamoDB ein Bean oder eine Map hinzuzufügen, bevor Sie eines ihrer Attribute aktualisieren.
+ `IgnoreNullsMode.MAPS_ONLY`- Verwenden Sie diese Einstellung, um Eigenschaften hinzuzufügen oder zu ersetzen, bei denen es sich um eine Bean oder Map handelt. Das SDK ersetzt oder fügt alle im Objekt bereitgestellten Maps oder Beans hinzu. Alle Beans oder Maps, die im Objekt Null sind, werden ignoriert, wobei die in DynamoDB vorhandene Map beibehalten wird.
+ `IgnoreNullsMode.DEFAULT`— Mit dieser Einstellung ignoriert das SDK niemals Nullwerte. Skalare Attribute auf jeder Ebene, die Null sind, werden auf Null aktualisiert. Das SDK aktualisiert alle Bean-, Map-, List- oder Set-Eigenschaften mit Nullwert im Objekt in DynamoDB auf Null. Wenn Sie diesen Modus verwenden — oder keinen Modus angeben, da es der Standardmodus ist — sollten Sie das Element zuerst abrufen, damit Werte in DynamoDB nicht auf Null gesetzt werden, die im Objekt zur Aktualisierung bereitgestellt werden, es sei denn, Sie beabsichtigen, die Werte auf Null zu setzen.

Wenn Sie in allen Modi ein Objekt mit einer Liste oder einem Satz angeben`updateItem`, der nicht Null ist, wird die Liste oder der Satz in DynamoDB gespeichert. 

#### Warum die Modi?
<a name="ddb-en-client-adv-features-nested-updates-nullmodes-why"></a>

Wenn Sie ein Objekt mit einem Bean oder einer Map für die `updateItem` Methode bereitstellen, kann das SDK nicht sagen, ob es die Eigenschaftswerte in der Bean (oder die Eintragswerte in der Map) verwenden soll, um das Element zu aktualisieren, oder ob das Ganze das ersetzen bean/map soll, was in DynamoDB gespeichert wurde.

Ausgehend von unserem vorherigen Beispiel, das zuerst den Abruf des Elements zeigt, versuchen wir, das `city` Attribut von `mainAddress` ohne den Abruf zu aktualisieren.

```
/* The retrieval example saved the Person object with a 'mainAddress' property whose 'city' property value is "MyCity".
/* Note that we create a new Person with only the necessary information to update the city value
of the mainAddress. */
Person personForUpdate = new Person();
personForUpdate.setId(1);
// The update we want to make changes the city.
Address mainAddressForUpdate = new Address();
mainAddressForUpdate.setCity("YourCity");
personForUpdate.setMainAddress(mainAddressForUpdate);

// Lets' try the following:
Person updatedPerson = personDynamoDbTable.updateItem(personForUpdate);
/*
 Since we haven't retrieved the item, we don't know if the 'mainAddress' property
 already exists, so what update expression should the SDK generate?

A) Should it replace or add the 'mainAddress' with the provided object (setting all attributes to null other than city)
   as shown in the following simplified JSON?

      {
        "TableName": "PersonTable",
        "Key": {
          "id": {
            "N": "1"
          }
        },
        "ReturnValues": "ALL_NEW",
        "UpdateExpression": "SET #mainAddress = :mainAddress",
        "ExpressionAttributeNames": {
          "#mainAddress": "mainAddress"
        },
        "ExpressionAttributeValues": {
          ":mainAddress": {
            "M": {
              "zipCode": {
                "NULL": true
              },
              "city": {
                "S": "YourCity"
              },
              "street": {
                "NULL": true
              },
              "state": {
                "NULL": true
              }
            }
          }
        }
      }
 
B) Or should it update only the 'city' attribute of an existing 'mainAddress' as shown in the following simplified JSON?

      {
        "TableName": "PersonTable",
        "Key": {
          "id": {
            "N": "1"
          }
        },
        "ReturnValues": "ALL_NEW",
        "UpdateExpression": "SET #mainAddress.#city = :mainAddress_city",
        "ExpressionAttributeNames": {
          "#city": "city",
          "#mainAddress": "mainAddress"
        },
        "ExpressionAttributeValues": {
          ":mainAddress_city": {
            "S": "YourCity"
          }
        }
      }

However, assume that we don't know if the 'mainAddress' already exists. If it doesn't exist, the SDK would try to update 
an attribute of a non-existent map, which results in an exception.

In this particular case, we would likely select option B (SCALAR_ONLY) to retain the other values of the 'mainAddress'.
*/
```

Die folgenden beiden Beispiele zeigen die Verwendung der Werte `MAPS_ONLY` und der `SCALAR_ONLY` Aufzählungswerte. `MAPS_ONLY`fügt eine Map hinzu und `SCALAR_ONLY` aktualisiert eine Map.

##### `IgnoreNullsMode.MAPS_ONLY`Beispiel für
<a name="scalar-only-example"></a>

```
    public void mapsOnlyModeExample() {
        // Assume that we ran this code yesterday.
        Person person = new Person();
        person.setId(1);
        person.setFirstName("FirstName");

        personDynamoDbTable.putItem(person);

        // Assume that we are running this code now.

        /* Note that we create a new Person with only the necessary information to update the city value
        of the mainAddress. */
        Person personForUpdate = new Person();
        personForUpdate.setId(1);
        // The update we want to make changes the city.
        Address mainAddressForUpdate = new Address();
        mainAddressForUpdate.setCity("YourCity");
        personForUpdate.setMainAddress(mainAddressForUpdate);


        Person updatedPerson = personDynamoDbTable.updateItem(r -> r
                .item(personForUpdate)
                .ignoreNullsMode(IgnoreNullsMode.MAPS_ONLY)); // Since the mainAddress property does not exist, use MAPS_ONLY mode.
        assert updatedPerson.getMainAddress().getCity().equals("YourCity");
        assert updatedPerson.getMainAddress().getState() == null;
    }
```

##### `IgnoreNullsMode.SCALAR_ONLY example`
<a name="maps-only-example"></a>

```
    public void scalarOnlyExample() {
        // Assume that we ran this code yesterday.
        Person person = new Person();
        person.setId(1);
        Address mainAddress = new Address();
        mainAddress.setCity("MyCity");
        mainAddress.setState("MyState");
        person.setMainAddress(mainAddress);

        personDynamoDbTable.putItem(person);

        // Assume that we are running this code now.

        /* Note that we create a new Person with only the necessary information to update the city value
        of the mainAddress. */
        Person personForUpdate = new Person();
        personForUpdate.setId(1);
        // The update we want to make changes the city.
        Address mainAddressForUpdate = new Address();
        mainAddressForUpdate.setCity("YourCity");
        personForUpdate.setMainAddress(mainAddressForUpdate);

        Person updatedPerson = personDynamoDbTable.updateItem(r -> r
                .item(personForUpdate)
                .ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY)); // SCALAR_ONLY mode ignores null properties in the in mainAddress.
        assert updatedPerson.getMainAddress().getCity().equals("YourCity");
        assert updatedPerson.getMainAddress().getState().equals("MyState"); // The state property remains the same.
    }
```

In der folgenden Tabelle können Sie nachlesen, welche Nullwerte für jeden Modus ignoriert werden. Sie können oft mit beiden `SCALAR_ONLY` arbeiten, `MAPS_ONLY` außer wenn Sie mit Beans oder Maps arbeiten.


**Welche Eigenschaften mit Nullwert in dem Objekt, an das gesendet wurde, ignoriert `updateItem` das SDK für jeden Modus?**  

| Art der Eigenschaft | im Modus SCALAR\$1ONLY | im MAPS\$1ONLY-Modus | im DEFAULT-Modus | 
| --- | --- | --- | --- | 
| Oberster Skalar | Ja | Ja | Nein | 
| Bean oder Karte | Ja | Ja | Nein | 
| Skalarwert eines Bean- oder Map-Eintrags | Ja1 | Nr.2 | Nein | 
| Liste oder Satz | Ja | Ja | Nein | 

1 Dies setzt voraus, dass die Map bereits in DynamoDB vorhanden ist. Jeder Skalarwert — Null oder nicht Null — der Bean oder Map, die Sie im Objekt für die Aktualisierung angeben, erfordert, dass ein Pfad zu dem Wert in DynamoDB existiert. Das SDK erstellt mithilfe des Dereferenzierungsoperators einen Pfad zu dem Attribut, bevor es die Anforderung sendet. `. (dot)`

2 Da Sie den `MAPS_ONLY` Modus verwenden, um eine Bean oder Map vollständig zu ersetzen oder hinzuzufügen, werden alle Nullwerte in der Bean oder Map in der in DynamoDB gespeicherten Map beibehalten.

# Leere Objekte konservieren mit `@DynamoDbPreserveEmptyObject`
<a name="ddb-en-client-adv-features-empty"></a>

Wenn Sie eine Bean mit leeren Objekten in Amazon DynamoDB speichern und möchten, dass das SDK die leeren Objekte beim Abrufen neu erstellt, kommentieren Sie den Getter der inneren Bean mit. `@DynamoDbPreserveEmptyObject`

Um zu veranschaulichen, wie die Anmerkung funktioniert, verwendet das Codebeispiel die folgenden beiden Beans.

## Beispiel Bohnen
<a name="ddb-en-client-adv-features-empty-ex1"></a>

Die folgende Datenklasse enthält zwei `InnerBean` Felder. Die Getter-Methode,`getInnerBeanWithoutAnno()`, ist nicht mit annotiert. `@DynamoDbPreserveEmptyObject` Die `getInnerBeanWithAnno()` Methode ist mit Anmerkungen versehen.

```
@DynamoDbBean
public class MyBean {

    private String id;
    private String name;
    private InnerBean innerBeanWithoutAnno;
    private InnerBean innerBeanWithAnno;

    @DynamoDbPartitionKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public InnerBean getInnerBeanWithoutAnno() { return innerBeanWithoutAnno; }
    public void setInnerBeanWithoutAnno(InnerBean innerBeanWithoutAnno) { this.innerBeanWithoutAnno = innerBeanWithoutAnno; }

    @DynamoDbPreserveEmptyObject
    public InnerBean getInnerBeanWithAnno() { return innerBeanWithAnno; }
    public void setInnerBeanWithAnno(InnerBean innerBeanWithAnno) { this.innerBeanWithAnno = innerBeanWithAnno; }

    @Override
    public String toString() {
        return new StringJoiner(", ", MyBean.class.getSimpleName() + "[", "]")
                .add("innerBeanWithoutAnno=" + innerBeanWithoutAnno)
                .add("innerBeanWithAnno=" + innerBeanWithAnno)
                .add("id='" + id + "'")
                .add("name='" + name + "'")
                .toString();
    }
}
```

Instanzen der folgenden `InnerBean` Klasse sind Felder von `MyBean` und werden im Beispielcode als leere Objekte initialisiert.

```
@DynamoDbBean
public class InnerBean {

    private String innerBeanField;

    public String getInnerBeanField() {
        return innerBeanField;
    }

    public void setInnerBeanField(String innerBeanField) {
        this.innerBeanField = innerBeanField;
    }

    @Override
    public String toString() {
        return "InnerBean{" +
                "innerBeanField='" + innerBeanField + '\'' +
                '}';
    }
}
```

Das folgende Codebeispiel speichert ein `MyBean` Objekt mit initialisierten inneren Beans in DynamoDB und ruft dann das Element ab. Die protokollierte Ausgabe zeigt, dass das `innerBeanWithoutAnno` nicht initialisiert wurde, sondern erstellt wurde. `innerBeanWithAnno`

```
    public MyBean preserveEmptyObjectAnnoUsingGetItemExample(DynamoDbTable<MyBean> myBeanTable) {
        // Save an item to DynamoDB.
        MyBean bean = new MyBean();
        bean.setId("1");
        bean.setInnerBeanWithoutAnno(new InnerBean());   // Instantiate the inner bean.
        bean.setInnerBeanWithAnno(new InnerBean());      // Instantiate the inner bean.
        myBeanTable.putItem(bean);

        GetItemEnhancedRequest request = GetItemEnhancedRequest.builder()
                .key(Key.builder().partitionValue("1").build())
                .build();
        MyBean myBean = myBeanTable.getItem(request);

        logger.info(myBean.toString());
        // Output 'MyBean[innerBeanWithoutAnno=null, innerBeanWithAnno=InnerBean{innerBeanField='null'}, id='1', name='null']'.

        return myBean;
    }
```

## Alternatives statisches Schema
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

Sie können die folgende `StaticTableSchema` Version der Tabellenschemas anstelle der Anmerkungen auf den Beans verwenden.

```
    public static TableSchema<MyBean> buildStaticSchemas() {

        StaticTableSchema<InnerBean> innerBeanStaticTableSchema =
                StaticTableSchema.builder(InnerBean.class)
                        .newItemSupplier(InnerBean::new)
                        .addAttribute(String.class, a -> a.name("innerBeanField")
                                .getter(InnerBean::getInnerBeanField)
                                .setter(InnerBean::setInnerBeanField))
                        .build();

        return StaticTableSchema.builder(MyBean.class)
                .newItemSupplier(MyBean::new)
                .addAttribute(String.class, a -> a.name("id")
                        .getter(MyBean::getId)
                        .setter(MyBean::setId)
                        .addTag(primaryPartitionKey()))
                .addAttribute(String.class, a -> a.name("name")
                        .getter(MyBean::getName)
                        .setter(MyBean::setName))
                .addAttribute(EnhancedType.documentOf(InnerBean.class,
                                innerBeanStaticTableSchema),
                        a -> a.name("innerBean1")
                                .getter(MyBean::getInnerBeanWithoutAnno)
                                .setter(MyBean::setInnerBeanWithoutAnno))
                .addAttribute(EnhancedType.documentOf(InnerBean.class,
                                innerBeanStaticTableSchema,
                                b -> b.preserveEmptyObject(true)),
                        a -> a.name("innerBean2")
                                .getter(MyBean::getInnerBeanWithAnno)
                                .setter(MyBean::setInnerBeanWithAnno))
                .build();
    }
```

# Vermeiden Sie das Speichern von Null-Attributen verschachtelter Objekte
<a name="ddb-en-client-adv-features-ignore-null"></a>

Sie können Null-Attribute verschachtelter Objekte überspringen, wenn Sie ein Datenklassenobjekt in DynamoDB speichern, indem Sie die Anmerkung anwenden. `@DynamoDbIgnoreNulls` Im Gegensatz dazu werden Attribute der obersten Ebene mit Nullwerten niemals in der Datenbank gespeichert.

Um zu veranschaulichen, wie die Anmerkung funktioniert, verwendet das Codebeispiel die folgenden beiden Beans.

## Beispiel Bohnen
<a name="ddb-en-client-adv-features-ignore-null-ex1"></a>

Die folgende Datenklasse enthält zwei `InnerBean` Felder. Die Getter-Methode,`getInnerBeanWithoutAnno()`, ist nicht annotiert. Die `getInnerBeanWithIgnoreNullsAnno()` Methode ist mit annotiert. `@DynamoDbIgnoreNulls`

```
@DynamoDbBean
public class MyBean {

    private String id;
    private String name;
    private InnerBean innerBeanWithoutAnno;
    private InnerBean innerBeanWithIgnoreNullsAnno;

    @DynamoDbPartitionKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public InnerBean getInnerBeanWithoutAnno() { return innerBeanWithoutAnno; }
    public void setInnerBeanWithoutAnno(InnerBean innerBeanWithoutAnno) { this.innerBeanWithoutAnno = innerBeanWithoutAnno; }

    @DynamoDbIgnoreNulls
    public InnerBean getInnerBeanWithIgnoreNullsAnno() { return innerBeanWithIgnoreNullsAnno; }
    public void setInnerBeanWithIgnoreNullsAnno(InnerBean innerBeanWithAnno) { this.innerBeanWithIgnoreNullsAnno = innerBeanWithAnno; }

    @Override
    public String toString() {
        return new StringJoiner(", ", MyBean.class.getSimpleName() + "[", "]")
                .add("innerBeanWithoutAnno=" + innerBeanWithoutAnno)
                .add("innerBeanWithIgnoreNullsAnno=" + innerBeanWithIgnoreNullsAnno)
                .add("id='" + id + "'")
                .add("name='" + name + "'")
                .toString();
    }
}
```

Instanzen der folgenden `InnerBean` Klasse sind Felder von `MyBean` und werden im folgenden Beispielcode verwendet.

```
@DynamoDbBean
public class InnerBean {

    private String innerBeanFieldString;
    private Integer innerBeanFieldInteger;

    public String getInnerBeanFieldString() { return innerBeanFieldString; }
    public void setInnerBeanFieldString(String innerBeanFieldString) { this.innerBeanFieldString = innerBeanFieldString; }

    public Integer getInnerBeanFieldInteger() { return innerBeanFieldInteger; }
    public void setInnerBeanFieldInteger(Integer innerBeanFieldInteger) { this.innerBeanFieldInteger = innerBeanFieldInteger; }

    @Override
    public String toString() {
        return new StringJoiner(", ", InnerBean.class.getSimpleName() + "[", "]")
                .add("innerBeanFieldString='" + innerBeanFieldString + "'")
                .add("innerBeanFieldInteger=" + innerBeanFieldInteger)
                .toString();
    }
}
```

Im folgenden Codebeispiel wird ein `InnerBean` Objekt erstellt und nur einem seiner beiden Attribute ein Wert zugewiesen. 

```
    public void ignoreNullsAnnoUsingPutItemExample(DynamoDbTable<MyBean> myBeanTable) {
        // Create an InnerBean object and give only one attribute a value.
        InnerBean innerBeanOneAttributeSet = new InnerBean();
        innerBeanOneAttributeSet.setInnerBeanFieldInteger(200);

        // Create a MyBean instance and use the same InnerBean instance both for attributes.
        MyBean bean = new MyBean();
        bean.setId("1");
        bean.setInnerBeanWithoutAnno(innerBeanOneAttributeSet);
        bean.setInnerBeanWithIgnoreNullsAnno(innerBeanOneAttributeSet);

        Map<String, AttributeValue> itemMap = myBeanTable.tableSchema().itemToMap(bean, true);
        logger.info(itemMap.toString());
        // Log the map that is sent to the database.
        // {innerBeanWithIgnoreNullsAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200)}), id=AttributeValue(S=1), innerBeanWithoutAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200), innerBeanFieldString=AttributeValue(NUL=true)})}
        
        // Save the MyBean object to the table.
        myBeanTable.putItem(bean);
    }
```

Um die Low-Level-Daten zu visualisieren, die an DynamoDB gesendet werden, protokolliert der Code die Attributzuordnung, bevor das Objekt gespeichert wird. `MyBean`

Die protokollierte Ausgabe zeigt, dass ein Attribut `innerBeanWithIgnoreNullsAnno` ausgegeben wird,

```
innerBeanWithIgnoreNullsAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200)})
```

Die `innerBeanWithoutAnno` Instanz gibt zwei Attribute aus. Ein Attribut hat einen Wert von 200 und das andere ist ein Nullwertattribut.

```
innerBeanWithoutAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200), innerBeanFieldString=AttributeValue(NUL=true)})
```

## JSON-Darstellung der Attributzuordnung
<a name="ddb-en-client-adv-features-ignore-null-ex2"></a>

Die folgende JSON-Darstellung macht es einfacher, die in DynamoDB gespeicherten Daten zu sehen.

```
{
  "id": {
    "S": "1"
  },
  "innerBeanWithIgnoreNullsAnno": {
    "M": {
      "innerBeanFieldInteger": {
        "N": "200"
      }
    }
  },
  "innerBeanWithoutAnno": {
    "M": {
      "innerBeanFieldInteger": {
        "N": "200"
      },
      "innerBeanFieldString": {
        "NULL": true
      }
    }
  }
}
```

## Alternatives statisches Schema
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

Sie können die folgende `StaticTableSchema` Version der Tabellenschemas anstelle von Datenklassenanmerkungen verwenden.

```
public static TableSchema<MyBean> buildStaticSchemas() {

    StaticTableSchema<InnerBean> innerBeanStaticTableSchema =
        StaticTableSchema.builder(InnerBean.class)
            .newItemSupplier(InnerBean::new)
            .addAttribute(String.class, a -> a.name("innerBeanFieldString")
                .getter(InnerBean::getInnerBeanFieldString)
                .setter(InnerBean::setInnerBeanFieldString))
            .addAttribute(Integer.class, a -> a.name("innerBeanFieldInteger")
                .getter(InnerBean::getInnerBeanFieldInteger)
                .setter(InnerBean::setInnerBeanFieldInteger))
            .build();

    return StaticTableSchema.builder(MyBean.class)
        .newItemSupplier(MyBean::new)
        .addAttribute(String.class, a -> a.name("id")
            .getter(MyBean::getId)
            .setter(MyBean::setId)
            .addTag(primaryPartitionKey()))
        .addAttribute(String.class, a -> a.name("name")
            .getter(MyBean::getName)
            .setter(MyBean::setName))
        .addAttribute(EnhancedType.documentOf(InnerBean.class,
                innerBeanStaticTableSchema),
            a -> a.name("innerBeanWithoutAnno")
                .getter(MyBean::getInnerBeanWithoutAnno)
                .setter(MyBean::setInnerBeanWithoutAnno))
        .addAttribute(EnhancedType.documentOf(InnerBean.class,
                innerBeanStaticTableSchema,
                b -> b.ignoreNulls(true)),
            a -> a.name("innerBeanWithIgnoreNullsAnno")
                .getter(MyBean::getInnerBeanWithIgnoreNullsAnno)
                .setter(MyBean::setInnerBeanWithIgnoreNullsAnno))
        .build();
}
```

# Arbeiten Sie mit JSON-Dokumenten mit der Enhanced Document API für DynamoDB
<a name="ddb-en-client-doc-api"></a>

Die [Enhanced Document API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) für AWS SDK for Java 2.x ist für die Arbeit mit dokumentenorientierten Daten konzipiert, die kein festes Schema haben. Sie können damit jedoch auch benutzerdefinierte Klassen verwenden, um einzelne Attribute zuzuordnen.

 Die Enhanced Document API ist der Nachfolger der [Document API](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/DynamoDB.html) der AWS SDK für Java Version v1.x.

**Contents**
+ [Beginnen Sie mit der Verwendung der Enhanced Document API](ddb-en-client-doc-api-steps.md)
  + [Erstellen Sie ein und ein `DocumentTableSchema` `DynamoDbTable`](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema)
+ [Erstellen Sie erweiterte Dokumente](ddb-en-client-doc-api-steps-create-ed.md)
  + [Aus einer JSON-Zeichenfolge erstellen](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromJson)
  + [Aus einzelnen Elementen zusammensetzen](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts)
+ [Führen Sie CRUD-Operationen durch](ddb-en-client-doc-api-steps-use.md)
+ [Greifen Sie als benutzerdefinierte Objekte auf erweiterte Dokumentattribute zu](ddb-en-client-doc-api-convert.md)
+ [Verwenden Sie eine `EnhancedDocument` ohne DynamoDB](ddb-en-client-doc-api-standalone.md)

# Beginnen Sie mit der Verwendung der Enhanced Document API
<a name="ddb-en-client-doc-api-steps"></a>

Die Enhanced Document API erfordert dieselben [Abhängigkeiten](ddb-en-client-getting-started.md#ddb-en-client-gs-dep) wie die DynamoDB Enhanced Client API. Außerdem ist eine [`DynamoDbEnhancedClient`Instanz](ddb-en-client-getting-started-dynamodbTable.md#ddb-en-client-getting-started-dynamodbTable-eclient) erforderlich, wie am Anfang dieses Themas beschrieben.

Da die Enhanced Document API mit Version 2.20.3 von veröffentlicht wurde AWS SDK for Java 2.x, benötigen Sie diese Version oder eine höhere Version.

## Erstellen Sie ein und ein `DocumentTableSchema` `DynamoDbTable`
<a name="ddb-en-client-doc-api-steps-createschema"></a>

[Um mithilfe der Enhanced Document API Befehle für eine DynamoDB-Tabelle aufzurufen, verknüpfen Sie die Tabelle mit einem clientseitigen DynamoDbTable < > -Ressourcenobjekt. EnhancedDocument](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html) 

Die `table()` Methode des erweiterten Clients erstellt eine `DynamoDbTable<EnhancedDocument>` Instanz und benötigt Parameter für den DynamoDB-Tabellennamen und a. `DocumentTableSchema` 

Der Builder für a [DocumentTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.html)erfordert einen primären Indexschlüssel und einen oder mehrere Attributkonverter-Anbieter. Die `AttributeConverterProvider.defaultProvider()` Methode stellt Konverter für [Standardtypen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/package-summary.html) bereit. Sie sollte auch dann angegeben werden, wenn Sie einen benutzerdefinierten Attributkonverter-Anbieter angeben. Sie können dem Builder einen optionalen sekundären Indexschlüssel hinzufügen.

Der folgende Codeausschnitt zeigt den Code, der die clientseitige Darstellung einer DynamoDB-Tabelle generiert, in der schemalose Objekte gespeichert `person` werden. `EnhancedDocument`

```
DynamoDbTable<EnhancedDocument> documentDynamoDbTable = 
                enhancedClient.table("person",
                        TableSchema.documentSchemaBuilder()
                            // Specify the primary key attributes.
                            .addIndexPartitionKey(TableMetadata.primaryIndexName(),"id", AttributeValueType.S)
                            .addIndexSortKey(TableMetadata.primaryIndexName(), "lastName", AttributeValueType.S)
                            // Specify attribute converter providers. Minimally add the default one.
                            .attributeConverterProviders(AttributeConverterProvider.defaultProvider())
                            .build());
                                                         
// Call documentTable.createTable() if "person" does not exist in DynamoDB.
// createTable() should be called only one time.
```

Im Folgenden wird die JSON-Darstellung eines Objekts gezeigt, die in diesem Abschnitt verwendet wird`person`.

### `person`JSON-Objekt
<a name="ddb-en-client-doc-api-steps-createschema-obj"></a>

```
{
  "id": 1,
  "firstName": "Richard",
  "lastName": "Roe",
  "age": 25,
  "addresses":
    {
      "home": {
        "zipCode": "00000",
        "city": "Any Town",
        "state": "FL",
        "street": "123 Any Street"
      },
      "work": {
        "zipCode": "00001",
        "city": "Anywhere",
        "state": "FL",
        "street": "100 Main Street"
      }
    },
  "hobbies": [
    "Hobby 1",
    "Hobby 2"
  ],
  "phoneNumbers": [
    {
      "type": "Home",
      "number": "555-0100"
    },
    {
      "type": "Work",
      "number": "555-0119"
    }
  ]
}
```

# Erstellen Sie erweiterte Dokumente
<a name="ddb-en-client-doc-api-steps-create-ed"></a>

An `[EnhancedDocument](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html)` steht für ein Objekt vom Typ Dokument mit einer komplexen Struktur mit verschachtelten Attributen. An `EnhancedDocument` erfordert Attribute der obersten Ebene, die den für den angegebenen Primärschlüsselattributen entsprechen. `DocumentTableSchema` Der restliche Inhalt ist willkürlich und kann aus Attributen der obersten Ebene und auch tief verschachtelten Attributen bestehen.

Sie erstellen eine `EnhancedDocument` Instanz mithilfe eines Builders, der mehrere Möglichkeiten zum Hinzufügen von Elementen bietet.

## Aus einer JSON-Zeichenfolge erstellen
<a name="ddb-en-client-doc-api-steps-create-ed-fromJson"></a>

Mit einer JSON-Zeichenfolge können Sie einen Methodenaufruf `EnhancedDocument` in einem Schritt erstellen. Das folgende Snippet erstellt `EnhancedDocument` aus einer JSON-Zeichenfolge, die von der `jsonPerson()` Hilfsmethode zurückgegeben wird. Die `jsonPerson()` Methode gibt die JSON-String-Version des zuvor gezeigten [Personenobjekts](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema-obj) zurück.

```
EnhancedDocument document = 
        EnhancedDocument.builder()
                        .json( jsonPerson() )
                        .build());
```

## Aus einzelnen Elementen zusammensetzen
<a name="ddb-en-client-doc-api-steps-create-ed-fromparts"></a>

Alternativ können Sie mit den typsicheren Methoden des Builders eine `EnhancedDocument` Instanz aus einzelnen Komponenten erstellen.

Im folgenden Beispiel wird ein `person` erweitertes Dokument erstellt, das dem erweiterten Dokument ähnelt, das aus der JSON-Zeichenfolge im vorherigen Beispiel erstellt wurde.

```
        /* Define the shape of an address map whose JSON representation looks like the following.
           Use 'addressMapEnhancedType' in the following EnhancedDocument.builder() to simplify the code.
           "home": {
             "zipCode": "00000",
             "city": "Any Town",
             "state": "FL",
             "street": "123 Any Street"
           }*/
        EnhancedType<Map<String, String>> addressMapEnhancedType =
                EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(String.class));


        //  Use the builder's typesafe methods to add elements to the enhanced document.
        EnhancedDocument personDocument = EnhancedDocument.builder()
                .putNumber("id", 50)
                .putString("firstName", "Shirley")
                .putString("lastName", "Rodriguez")
                .putNumber("age", 53)
                .putNull("nullAttribute")
                .putJson("phoneNumbers", phoneNumbersJSONString())
                /* Add the map of addresses whose JSON representation looks like the following.
                        {
                          "home": {
                            "zipCode": "00000",
                            "city": "Any Town",
                            "state": "FL",
                            "street": "123 Any Street"
                          }
                        } */
                .putMap("addresses", getAddresses(), EnhancedType.of(String.class), addressMapEnhancedType)
                .putList("hobbies", List.of("Theater", "Golf"), EnhancedType.of(String.class))
                .build();
```

### Hilfsmethoden
<a name="ddb-en-client-doc-api-steps-use-fromparts-helpers"></a>

```
    private static String phoneNumbersJSONString() {
        return "  [" +
                "    {" +
                "      \"type\": \"Home\"," +
                "      \"number\": \"555-0140\"" +
                "    }," +
                "    {" +
                "      \"type\": \"Work\"," +
                "      \"number\": \"555-0155\"" +
                "    }" +
                "  ]";
    }

    private static Map<String, Map<String, String>> getAddresses() {
        return Map.of(
                "home", Map.of(
                        "zipCode", "00002",
                        "city", "Any Town",
                        "state", "ME",
                        "street", "123 Any Street"));

    }
```

# Führen Sie CRUD-Operationen durch
<a name="ddb-en-client-doc-api-steps-use"></a>

Nachdem Sie eine `EnhancedDocument` Instanz definiert haben, können Sie sie in einer DynamoDB-Tabelle speichern. Der folgende Codeausschnitt verwendet das [PersonDocument, das aus einzelnen Elementen](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts) erstellt wurde.

```
documentDynamoDbTable.putItem(personDocument);
```

Nachdem Sie eine erweiterte Dokumentinstanz aus DynamoDB gelesen haben, können Sie die einzelnen Attributwerte mithilfe von Getter extrahieren, wie im folgenden Codeausschnitt gezeigt, die auf die Daten zugreifen, die aus dem gespeichert wurden. `personDocument` Alternativ können Sie den gesamten Inhalt in eine JSON-Zeichenfolge extrahieren, wie im letzten Teil des Beispielcodes gezeigt.

```
        // Read the item.
        EnhancedDocument personDocFromDb = documentDynamoDbTable.getItem(Key.builder().partitionValue(50).build());

        // Access top-level attributes.
        logger.info("Name: {} {}", personDocFromDb.getString("firstName"), personDocFromDb.getString("lastName"));
        // Name: Shirley Rodriguez

        // Typesafe access of a deeply nested attribute. The addressMapEnhancedType shown previously defines the shape of an addresses map.
        Map<String, Map<String, String>> addresses = personDocFromDb.getMap("addresses", EnhancedType.of(String.class), addressMapEnhancedType);
        addresses.keySet().forEach(k -> logger.info(addresses.get(k).toString()));
        // {zipCode=00002, city=Any Town, street=123 Any Street, state=ME}

        // Alternatively, work with AttributeValue types checking along the way for deeply nested attributes.
        Map<String, AttributeValue> addressesMap = personDocFromDb.getMapOfUnknownType("addresses");
        addressesMap.keySet().forEach((String k) -> {
            logger.info("Looking at data for [{}] address", k);
            // Looking at data for [home] address
            AttributeValue value = addressesMap.get(k);
            AttributeValue cityValue = value.m().get("city");
            if (cityValue != null) {
                logger.info(cityValue.s());
                // Any Town
            }
        });

        List<AttributeValue> phoneNumbers = personDocFromDb.getListOfUnknownType("phoneNumbers");
        phoneNumbers.forEach((AttributeValue av) -> {
            if (av.hasM()) {
                AttributeValue type = av.m().get("type");
                if (type.s() != null) {
                    logger.info("Type of phone: {}", type.s());
                    // Type of phone: Home
                    // Type of phone: Work
                }
            }
        });

        String jsonPerson = personDocFromDb.toJson();
        logger.info(jsonPerson);
        // {"firstName":"Shirley","lastName":"Rodriguez","addresses":{"home":{"zipCode":"00002","city":"Any Town","street":"123 Any Street","state":"ME"}},"hobbies":["Theater","Golf"],
        //     "id":50,"nullAttribute":null,"age":53,"phoneNumbers":[{"number":"555-0140","type":"Home"},{"number":"555-0155","type":"Work"}]}
```

`EnhancedDocument`Instanzen können mit jeder Methode von `[DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)` oder [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)anstelle von zugewiesenen Datenklassen verwendet werden.

# Greifen Sie als benutzerdefinierte Objekte auf erweiterte Dokumentattribute zu
<a name="ddb-en-client-doc-api-convert"></a>

Die Enhanced Document API bietet nicht nur eine API zum Lesen und Schreiben von Attributen mit schemalosen Strukturen, sondern ermöglicht auch die Konvertierung von Attributen in und aus Instanzen benutzerdefinierter Klassen.

Die Enhanced Document API verwendet `AttributeConverterProvider` s und `AttributeConverter` s, die im Abschnitt zur [Konvertierung von Steuerattributen](ddb-en-client-adv-features-conversion.md) als Teil der DynamoDB Enhanced Client API angezeigt wurden.

Im folgenden Beispiel verwenden wir a `CustomAttributeConverterProvider` mit seiner verschachtelten `AddressConverter` Klasse, um Objekte zu konvertieren. `Address` 

Dieses Beispiel zeigt, dass Sie Daten aus Klassen und auch Daten aus Strukturen kombinieren können, die nach Bedarf erstellt werden. Dieses Beispiel zeigt auch, dass benutzerdefinierte Klassen auf jeder Ebene einer verschachtelten Struktur verwendet werden können. Die `Address` Objekte in diesem Beispiel sind Werte, die in einer Map verwendet werden.

```
    public static void attributeToAddressClassMappingExample(DynamoDbEnhancedClient enhancedClient, DynamoDbClient standardClient) {
        String tableName = "customer";

        // Define the DynamoDbTable for an enhanced document.
        // The schema builder provides methods for attribute converter providers and keys.
        DynamoDbTable<EnhancedDocument> documentDynamoDbTable = enhancedClient.table(tableName,
                DocumentTableSchema.builder()
                        // Add the CustomAttributeConverterProvider along with the default when you build the table schema.
                        .attributeConverterProviders(
                                List.of(
                                        new CustomAttributeConverterProvider(),
                                        AttributeConverterProvider.defaultProvider()))
                        .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", AttributeValueType.N)
                        .addIndexSortKey(TableMetadata.primaryIndexName(), "lastName", AttributeValueType.S)
                        .build());
        // Create the DynamoDB table if needed.
        documentDynamoDbTable.createTable();
        waitForTableCreation(tableName, standardClient);


        // The getAddressesForCustomMappingExample() helper method that provides 'addresses' shows the use of a custom Address class
        // rather than using a Map<String, Map<String, String> to hold the address data.
        Map<String, Address> addresses = getAddressesForCustomMappingExample();

        // Build an EnhancedDocument instance to save an item with a mix of structures defined as needed and static classes.
        EnhancedDocument personDocument = EnhancedDocument.builder()
                .putNumber("id", 50)
                .putString("firstName", "Shirley")
                .putString("lastName", "Rodriguez")
                .putNumber("age", 53)
                .putNull("nullAttribute")
                .putJson("phoneNumbers", phoneNumbersJSONString())
                // Note the use of 'EnhancedType.of(Address.class)' instead of the more generic
                // 'EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(String.class))' that was used in a previous example.
                .putMap("addresses", addresses, EnhancedType.of(String.class), EnhancedType.of(Address.class))
                .putList("hobbies", List.of("Hobby 1", "Hobby 2"), EnhancedType.of(String.class))
                .build();
        // Save the item to DynamoDB.
        documentDynamoDbTable.putItem(personDocument);

        // Retrieve the item just saved.
        EnhancedDocument srPerson = documentDynamoDbTable.getItem(Key.builder().partitionValue(50).sortValue("Rodriguez").build());

        // Access the addresses attribute.
        Map<String, Address> srAddresses = srPerson.get("addresses",
                EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(Address.class)));

        srAddresses.keySet().forEach(k -> logger.info(addresses.get(k).toString()));

        documentDynamoDbTable.deleteTable();

// The content logged to the console shows that the saved maps were converted to Address instances.
Address{street='123 Main Street', city='Any Town', state='NC', zipCode='00000'}
Address{street='100 Any Street', city='Any Town', state='NC', zipCode='00000'}
```

## `CustomAttributeConverterProvider`-Code
<a name="ddb-en-client-doc-api-convert-provider"></a>

```
public class CustomAttributeConverterProvider implements AttributeConverterProvider {

    private final Map<EnhancedType<?>, AttributeConverter<?>> converterCache = ImmutableMap.of(
            // 1. Add AddressConverter to the internal cache.
            EnhancedType.of(Address.class), new AddressConverter());

    public static CustomAttributeConverterProvider create() {
        return new CustomAttributeConverterProvider();
    }

    // 2. The enhanced client queries the provider for attribute converters if it
    //    encounters a type that it does not know how to convert.
    @SuppressWarnings("unchecked")
    @Override
    public <T> AttributeConverter<T> converterFor(EnhancedType<T> enhancedType) {
        return (AttributeConverter<T>) converterCache.get(enhancedType);
    }

    // 3. Custom attribute converter
    private class AddressConverter implements AttributeConverter<Address> {
        // 4. Transform an Address object into a DynamoDB map.
        @Override
        public AttributeValue transformFrom(Address address) {

            Map<String, AttributeValue> attributeValueMap = Map.of(
                    "street", AttributeValue.fromS(address.getStreet()),
                    "city", AttributeValue.fromS(address.getCity()),
                    "state", AttributeValue.fromS(address.getState()),
                    "zipCode", AttributeValue.fromS(address.getZipCode()));

            return AttributeValue.fromM(attributeValueMap);
        }

        // 5. Transform the DynamoDB map attribute to an Address oject.
        @Override
        public Address transformTo(AttributeValue attributeValue) {
            Map<String, AttributeValue> m = attributeValue.m();
            Address address = new Address();
            address.setStreet(m.get("street").s());
            address.setCity(m.get("city").s());
            address.setState(m.get("state").s());
            address.setZipCode(m.get("zipCode").s());

            return address;
        }

        @Override
        public EnhancedType<Address> type() {
            return EnhancedType.of(Address.class);
        }

        @Override
        public AttributeValueType attributeValueType() {
            return AttributeValueType.M;
        }
    }
}
```

## `Address`-Klasse
<a name="ddb-en-client-doc-api-convert-address"></a>

```
public class Address {
                  private String street;
                  private String city;
                  private String state;
                  private String zipCode;

                  public Address() {
                  }

                  public String getStreet() {
                  return this.street;
                  }

                  public String getCity() {
                  return this.city;
                  }

                  public String getState() {
                  return this.state;
                  }

                  public String getZipCode() {
                  return this.zipCode;
                  }

                  public void setStreet(String street) {
                  this.street = street;
                  }

                  public void setCity(String city) {
                  this.city = city;
                  }

                  public void setState(String state) {
                  this.state = state;
                  }

                  public void setZipCode(String zipCode) {
                  this.zipCode = zipCode;
                  }
                  }
```

## Hilfsmethode, die Adressen bereitstellt
<a name="ddb-en-client-doc-api-convert-helper"></a>

Die folgende Hilfsmethode stellt die Map bereit, die benutzerdefinierte `Address` Instanzen für Werte anstelle von generischen `Map<String, String>` Instanzen für Werte verwendet.

```
    private static Map<String, Address> getAddressesForCustomMappingExample() {
        Address homeAddress = new Address();
        homeAddress.setStreet("100 Any Street");
        homeAddress.setCity("Any Town");
        homeAddress.setState("NC");
        homeAddress.setZipCode("00000");

        Address workAddress = new Address();
        workAddress.setStreet("123 Main Street");
        workAddress.setCity("Any Town");
        workAddress.setState("NC");
        workAddress.setZipCode("00000");

        return Map.of("home", homeAddress,
                "work", workAddress);
    }
```

# Verwenden Sie eine `EnhancedDocument` ohne DynamoDB
<a name="ddb-en-client-doc-api-standalone"></a>

Normalerweise verwenden Sie eine Instanz von an, `EnhancedDocument` um DynamoDB-Elemente vom Typ Dokument zu lesen und zu schreiben, sie kann jedoch auch unabhängig von DynamoDB verwendet werden. 

Sie können ihre Fähigkeit verwenden`EnhancedDocuments`, zwischen JSON-Zeichenfolgen oder benutzerdefinierten Objekten in Low-Level-Maps von `AttributeValues` zu konvertieren, wie im folgenden Beispiel gezeigt.

```
    public static void conversionWithoutDynamoDbExample() {
        Address address = new Address();
        address.setCity("my city");
        address.setState("my state");
        address.setStreet("my street");
        address.setZipCode("00000");

        // Build an EnhancedDocument instance for its conversion functionality alone.
        EnhancedDocument addressEnhancedDoc = EnhancedDocument.builder()
                // Important: You must specify attribute converter providers when you build an EnhancedDocument instance not used with a DynamoDB table.
                .attributeConverterProviders(new CustomAttributeConverterProvider(), DefaultAttributeConverterProvider.create())
                .put("addressDoc", address, Address.class)
                .build();

        // Convert address to a low-level item representation.
        final Map<String, AttributeValue> addressAsAttributeMap = addressEnhancedDoc.getMapOfUnknownType("addressDoc");
        logger.info("addressAsAttributeMap: {}", addressAsAttributeMap.toString());

        // Convert address to a JSON string.
        String addressAsJsonString = addressEnhancedDoc.getJson("addressDoc");
        logger.info("addressAsJsonString: {}", addressAsJsonString);
        // Convert addressEnhancedDoc back to an Address instance.
        Address addressConverted =  addressEnhancedDoc.get("addressDoc", Address.class);
        logger.info("addressConverted: {}", addressConverted.toString());
    }

   /* Console output:
          addressAsAttributeMap: {zipCode=AttributeValue(S=00000), state=AttributeValue(S=my state), street=AttributeValue(S=my street), city=AttributeValue(S=my city)}
          addressAsJsonString: {"zipCode":"00000","state":"my state","street":"my street","city":"my city"}
          addressConverted: Address{street='my street', city='my city', state='my state', zipCode='00000'}
   */
```

**Anmerkung**  
Wenn Sie ein erweitertes Dokument verwenden, das unabhängig von einer DynamoDB-Tabelle ist, stellen Sie sicher, dass Sie im Builder explizit Attributkonverter-Anbieter festlegen.  
Im Gegensatz dazu stellt das Dokumenttabellenschema die Konverteranbieter bereit, wenn ein erweitertes Dokument mit einer DynamoDB-Tabelle verwendet wird.

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

# Verwenden Sie die DynamoDB Enhanced Client API asynchron
<a name="ddb-en-client-async"></a>

Wenn Ihre Anwendung nicht blockierende, asynchrone Aufrufe von DynamoDB erfordert, können Sie den verwenden. [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html) Sie ähnelt der synchronen Implementierung, weist jedoch die folgenden wesentlichen Unterschiede auf:

1. Wenn Sie den erstellen`DynamoDbEnhancedAsyncClient`, müssen Sie die asynchrone Version des Standardclients bereitstellen`DynamoDbAsyncClient`, wie im folgenden Codeausschnitt dargestellt.

   ```
    DynamoDbEnhancedAsyncClient enhancedClient = 
        DynamoDbEnhancedAsyncClient.builder()
                                   .dynamoDbClient(dynamoDbAsyncClient)
                                   .build();
   ```

1. Methoden, die ein einzelnes Datenobjekt zurückgeben, geben nicht nur das Ergebnis zurück. `CompletableFuture` Ihre Anwendung kann dann andere Aufgaben ausführen, ohne das Ergebnis blockieren zu müssen. Der folgende Ausschnitt zeigt die asynchrone `getItem()` Methode. 

   ```
   CompletableFuture<Customer> result = customerDynamoDbTable.getItem(customer);
   // Perform other work here.
   return result.join();   // Now block and wait for the result.
   ```

1. Methoden, die paginierte Ergebnislisten zurückgeben, geben [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html)statt eines zurück [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html), das die synchrone Methode für dieselben Methoden `DynamoDbEnhanceClient` zurückgibt. Ihre Anwendung kann dann einen Handler für diesen Herausgeber abonnieren, um die Ergebnisse asynchron zu verarbeiten, ohne sie blockieren zu müssen.

   ```
   PagePublisher<Customer> results = customerDynamoDbTable.query(r -> r.queryConditional(keyEqualTo(k -> k.partitionValue("Smith"))));
   results.subscribe(myCustomerResultsProcessor);
   // Perform other work and let the processor handle the results asynchronously.
   ```

   Ein vollständigeres Beispiel für die Arbeit mit dem `SdkPublisher API` finden Sie in [dem Beispiel](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-scan-async) in dem Abschnitt, in dem die asynchrone `scan()` Methode beschrieben wird.

# Anmerkungen zu Datenklassen
<a name="ddb-en-client-anno-index"></a>

In der folgenden Tabelle sind die Anmerkungen aufgeführt, die für Datenklassen verwendet werden können, und sie enthält Links zu Informationen und Beispielen in diesem Handbuch. Die Tabelle ist in aufsteigender alphabetischer Reihenfolge nach dem Namen der Anmerkung sortiert.


**Anmerkungen zur Datenklasse, die in diesem Handbuch verwendet werden**  

| Name der Anmerkung | Anmerkung bezieht sich auf 1 | Was macht es | Wo es in diesem Handbuch gezeigt wird | 
| --- | --- | --- | --- | 
| DynamoDbAtomicCounter | Attribut 2 | Inkrementiert ein mit Tags versehenes numerisches Attribut jedes Mal, wenn ein Datensatz in die Datenbank geschrieben wird. | [Einführung und Diskussion.](ddb-en-client-extensions.md#ddb-en-client-extensions-ACE) | 
| DynamoDbAttribute | Attribut | Definiert oder benennt eine Bean-Eigenschaft um, die einem DynamoDB-Tabellenattribut zugeordnet ist. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbAutoGeneratedTimestampAttribute | Attribut | Aktualisiert jedes Mal, wenn das Element erfolgreich in die Datenbank geschrieben wurde, ein mit einem Tag versehenes Attribut mit einem aktuellen Zeitstempel | [Einführung und Diskussion](ddb-en-client-extensions.md#ddb-en-client-extensions-AGTE). | 
| DynamoDbAutoGeneratedUuid | Attribut | Generieren Sie eine eindeutige UUID (Universally Unique Identifier) für ein Attribut, wenn ein neuer Datensatz in die Datenbank geschrieben wird. | [Einführung und Diskussion.](ddb-en-client-extensions.md#ddb-en-client-extensions-AGUE) | 
| DynamoDbBean | class | Markiert eine Datenklasse als einem Tabellenschema zuordbar. | Erste Anwendung in der [Kundenklasse](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) im Abschnitt Erste Schritte. Im gesamten Handbuch werden verschiedene Verwendungen verwendet. | 
| DynamoDbConvertedBy | Attribut | Ordnet dem annotierten AttributeConverter Attribut einen benutzerdefinierten Wert zu. | [Erste Diskussion und Beispiel.](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-single) | 
| DynamoDbFlatten | Attribut | Reduziert alle Attribute einer separaten DynamoDB-Datenklasse und fügt sie dem Datensatz, der in die Datenbank gelesen und geschrieben wird, als Attribute der obersten Ebene hinzu.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnore | Attribut |  Führt dazu, dass das Attribut nicht zugeordnet wird.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnoreNulls | Attribut | Verhindert das Speichern von Null-Attributen verschachtelter DynamoDb Objekte. | [Diskussion und Beispiele.](ddb-en-client-adv-features-ignore-null.md) | 
| DynamoDbImmutable | class |  Markiert eine unveränderliche Datenklasse als einem Tabellenschema zuordbar.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPartitionKey | Attribut |  Markiert ein Attribut als primären Partitionsschlüssel (Hash-Schlüssel) der DynamoDb Tabelle.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPreserveEmptyObject | Attribut |  Gibt an, dass das Objekt mit allen Nullfeldern initialisiert werden soll, wenn keine Daten für das Objekt vorhanden sind, das dem annotierten Attribut zugeordnet ist.  | [Diskussion und Beispiele.](ddb-en-client-adv-features-empty.md) | 
| DynamoDbSecondaryPartitionKey | Attribut |  Markiert ein Attribut als Partitionsschlüssel für einen globalen sekundären Index.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSecondarySortKey | Attribut |  Markiert ein Attribut als optionalen Sortierschlüssel für einen globalen oder lokalen Sekundärindex.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSortKey | Attribut |  Markiert ein Attribut als optionalen primären Sortierschlüssel (Bereichsschlüssel).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbUpdateBehavior | Attribut |  Gibt das Verhalten an, wenn dieses Attribut im Rahmen eines Aktualisierungsvorgangs aktualisiert wird, UpdateItem z.  | [Einführung und Beispiel.](ddb-en-client-adv-features-upd-behavior.md) | 
| DynamoDbVersionAttribute | Attribut | Erhöht die Versionsnummer eines Artikels. | [Einführung und Diskussion.](ddb-en-client-extensions.md#ddb-en-client-extensions-VRE) | 

1 Sie können Anmerkungen auf Attributebene auf Getter oder Setter anwenden, aber nicht auf beide. Diese Anleitung zeigt Anmerkungen zu Getter.

2 Der Begriff `property` wird normalerweise für einen Wert verwendet, der in einer Datenklasse gekapselt ist. JavaBean In diesem Handbuch wird der Begriff jedoch `attribute` stattdessen verwendet, um mit der von DynamoDB verwendeten Terminologie konsistent zu sein.