

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.

# Durchführen von DynamoDB-Transaktionen in AWS AppSync
<a name="tutorial-dynamodb-transact"></a>

**Anmerkung**  
Wir unterstützen jetzt hauptsächlich die APPSYNC\$1JS-Laufzeit und ihre Dokumentation. [Bitte erwägen Sie, die APPSYNC\$1JS-Laufzeit und ihre Anleitungen hier zu verwenden.](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html)

AWS AppSync unterstützt die Verwendung von Amazon DynamoDB-Transaktionsoperationen für eine oder mehrere Tabellen in einer einzigen Region. Zu den unterstützten Operationen gehören `TransactGetItems` und `TransactWriteItems`. Mithilfe dieser Funktionen können Sie Aufgaben wie die folgenden ausführen: AWS AppSync
+ Übermitteln einer Liste von Schlüsseln in einer einzigen Abfrage und Zurückgabe der Ergebnisse aus einer Tabelle
+ Lesen der Datensätze aus einer oder mehrerer Tabellen in einer einzigen Abfrage
+ Schreiben Sie Datensätze in einer Transaktion auf irgendeine all-or-nothing Weise in eine oder mehrere Tabellen
+ Ausführen von Transaktionen, wenn einige Bedingungen erfüllt sind

## Berechtigungen
<a name="permissions"></a>

Wie bei anderen Resolvern müssen Sie eine Datenquelle in erstellen AWS AppSync und entweder eine Rolle erstellen oder eine vorhandene verwenden. Da Transaktionsvorgänge unterschiedliche Berechtigungen für DynamoDB-Tabellen erfordern, müssen Sie den konfigurierten Rollen Berechtigungen für Lese- oder Schreibaktionen gewähren:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:Scan",
                "dynamodb:UpdateItem"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:dynamodb:us-east-1:111122223333:table/TABLENAME",
                "arn:aws:dynamodb:us-east-1:111122223333:table/TABLENAME/*"
            ]
        }
    ]
}
```

------

 **Hinweis**: Rollen sind an Datenquellen in einer Datenquelle gebunden AWS AppSync, und Resolver für Felder werden für eine Datenquelle aufgerufen. Für Datenquellen, die für den Abruf von DynamoDB konfiguriert sind, ist nur eine Tabelle angegeben, um die Konfiguration zu vereinfachen. Möchten Sie jedoch einen Transaktionsvorgang an mehreren Tabellen mit nur einem Resolver ausführen, stellt dies eine erweiterte Aufgabe dar, und Sie müssen der Rolle dieser Datenquelle Zugriff auf alle Tabellen gewähren, mit denen der Resolver interagieren wird. Dies kann im Feld **Ressource (Resource)** in der IAM-Richtlinie weiter oben eingerichtet werden. Die Konfiguration der Tabellen, um Transaktionsaufrufe auszuführen, erfolgt in der Resolver-Vorlage und wird nachfolgend beschrieben.

## Datenquelle
<a name="data-source"></a>

Der Einfachheit halber verwenden wir die gleiche Datenquelle für alle in diesem Tutorial verwendeten Resolver. Erstellen Sie auf der Registerkarte **Datenquellen** eine neue DynamoDB-Datenquelle und geben Sie ihr einen Namen. **TransactTutorial** Sie können den Namen der Tabelle frei wählen, da Tabellennamen als Teil der Zuweisungsvorlage für Anforderungen bei Transaktionsvorgängen angegeben werden. Wir geben der Tabelle den Namen `empty`.

Wir haben zwei Tabellen mit den Bezeichnungen **savingAccounts** und **checkingAccounts**, beide mit `accountNumber` als Partitionsschlüssel, und eine **transactionHistory**-Tabelle mit `transactionId` als Partitionsschlüssel.

Für dieses Tutorial kann jede Rolle mit der folgenden eingebundenen Richtlinie verwendet werden: Ersetzen Sie `region` und `accountId` durch Ihre Region und Konto-ID:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:Scan",
                "dynamodb:UpdateItem"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:dynamodb:us-east-1:111122223333:table/savingAccounts",
                "arn:aws:dynamodb:us-east-1:111122223333:table/savingAccounts/*",
                "arn:aws:dynamodb:us-east-1:111122223333:table/checkingAccounts",
                "arn:aws:dynamodb:us-east-1:111122223333:table/checkingAccounts/*",
                "arn:aws:dynamodb:us-east-1:111122223333:table/transactionHistory",
                "arn:aws:dynamodb:us-east-1:111122223333:table/transactionHistory/*"
            ]
        }
    ]
}
```

------

## Transaktionen
<a name="transactions"></a>

Für dieses Beispiel ist der Kontext eine klassische Banktransaktion, bei der wir `TransactWriteItems` für folgende Aktionen verwenden:
+ Überweisen von Geld von Sparkonten auf Girokonten
+ Generieren neuer Transaktionsdatensätze für jede Transaktion

Anschließend verwenden wir `TransactGetItems`, um Details der Sparkonten und Girokonten abzurufen.

**Warnung**  
`TransactWriteItems`wird nicht unterstützt, wenn es zusammen mit Konflikterkennung und Konfliktlösung verwendet wird. Diese Einstellungen müssen deaktiviert werden, um mögliche Fehler zu vermeiden.

Wir definieren unser GraphQL-Schema wie folgt:

```
type SavingAccount {
    accountNumber: String!
    username: String
    balance: Float
}

type CheckingAccount {
    accountNumber: String!
    username: String
    balance: Float
}

type TransactionHistory {
    transactionId: ID!
    from: String
    to: String
    amount: Float
}

type TransactionResult {
    savingAccounts: [SavingAccount]
    checkingAccounts: [CheckingAccount]
    transactionHistory: [TransactionHistory]
}

input SavingAccountInput {
    accountNumber: String!
    username: String
    balance: Float
}

input CheckingAccountInput {
    accountNumber: String!
    username: String
    balance: Float
}

input TransactionInput {
    savingAccountNumber: String!
    checkingAccountNumber: String!
    amount: Float!
}

type Query {
    getAccounts(savingAccountNumbers: [String], checkingAccountNumbers: [String]): TransactionResult
}

type Mutation {
    populateAccounts(savingAccounts: [SavingAccountInput], checkingAccounts: [CheckingAccountInput]): TransactionResult
    transferMoney(transactions: [TransactionInput]): TransactionResult
}

schema {
    query: Query
    mutation: Mutation
}
```

### TransactWriteItems - Konten auffüllen
<a name="transactwriteitems-populate-accounts"></a>

Um Geld zwischen Konten zu übertragen, müssen wir die Tabelle mit den Details füllen. Wir verwenden dazu die GraphQL-Operation `Mutation.populateAccounts`.

Klicken Sie im Abschnitt Schema neben dem `Mutation.populateAccounts` Vorgang auf **Anhängen**. Gehen Sie zu VTL Unit Resolvers und wählen Sie dann dieselbe `TransactTutorial` Datenquelle aus.

Verwenden Sie die folgende Zuweisungsvorlage für Anforderungen:

 **Zuweisungsvorlage für Anforderungen** 

```
#set($savingAccountTransactPutItems = [])
#set($index = 0)
#foreach($savingAccount in ${ctx.args.savingAccounts})
    #set($keyMap = {})
    $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($savingAccount.accountNumber)))
    #set($attributeValues = {})
    $util.qr($attributeValues.put("username", $util.dynamodb.toString($savingAccount.username)))
    $util.qr($attributeValues.put("balance", $util.dynamodb.toNumber($savingAccount.balance)))
    #set($index = $index + 1)
    #set($savingAccountTransactPutItem = {"table": "savingAccounts",
        "operation": "PutItem",
        "key": $keyMap,
        "attributeValues": $attributeValues})
    $util.qr($savingAccountTransactPutItems.add($savingAccountTransactPutItem))
#end

#set($checkingAccountTransactPutItems = [])
#set($index = 0)
#foreach($checkingAccount in ${ctx.args.checkingAccounts})
    #set($keyMap = {})
    $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($checkingAccount.accountNumber)))
    #set($attributeValues = {})
    $util.qr($attributeValues.put("username", $util.dynamodb.toString($checkingAccount.username)))
    $util.qr($attributeValues.put("balance", $util.dynamodb.toNumber($checkingAccount.balance)))
    #set($index = $index + 1)
    #set($checkingAccountTransactPutItem = {"table": "checkingAccounts",
        "operation": "PutItem",
        "key": $keyMap,
        "attributeValues": $attributeValues})
    $util.qr($checkingAccountTransactPutItems.add($checkingAccountTransactPutItem))
#end

#set($transactItems = [])
$util.qr($transactItems.addAll($savingAccountTransactPutItems))
$util.qr($transactItems.addAll($checkingAccountTransactPutItems))

{
    "version" : "2018-05-29",
    "operation" : "TransactWriteItems",
    "transactItems" : $util.toJson($transactItems)
}
```

Und die folgende Zuweisungsvorlage für Antworten:

 **Zuweisungsvorlage für Antworten** 

```
#if ($ctx.error)
    $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons)
#end

#set($savingAccounts = [])
#foreach($index in [0..2])
    $util.qr($savingAccounts.add(${ctx.result.keys[$index]}))
#end

#set($checkingAccounts = [])
#foreach($index in [3..5])
    $util.qr($checkingAccounts.add(${ctx.result.keys[$index]}))
#end

#set($transactionResult = {})
$util.qr($transactionResult.put('savingAccounts', $savingAccounts))
$util.qr($transactionResult.put('checkingAccounts', $checkingAccounts))

$util.toJson($transactionResult)
```

Speichern Sie den Resolver und navigieren Sie zum Abschnitt **Abfragen** der AWS AppSync Konsole, um die Konten aufzufüllen.

Führen Sie die folgende Mutation aus:

```
mutation populateAccounts {
  populateAccounts (
    savingAccounts: [
      {accountNumber: "1", username: "Tom", balance: 100},
      {accountNumber: "2", username: "Amy", balance: 90},
      {accountNumber: "3", username: "Lily", balance: 80},
    ]
    checkingAccounts: [
      {accountNumber: "1", username: "Tom", balance: 70},
      {accountNumber: "2", username: "Amy", balance: 60},
      {accountNumber: "3", username: "Lily", balance: 50},
    ]) {
    savingAccounts {
      accountNumber
    }
    checkingAccounts {
      accountNumber
    }
  }
}
```

Wir haben drei Sparkonten und drei Girokonten in einer Mutation gefüllt.

**Verwenden Sie die DynamoDB-Konsole, um zu überprüfen, ob Daten sowohl in den Tabellen **SavingAccounts als auch in checkingAccounts** angezeigt werden.**

### TransactWriteItems - Geld überweisen
<a name="transactwriteitems-transfer-money"></a>

Fügen Sie der `transferMoney`-Mutation mithilfe der folgenden **Zuweisungsvorlage für Anforderungen** einen Resolver an. Beachten Sie, dass die Werte von `amounts`, `savingAccountNumbers` und `checkingAccountNumbers` identisch sind.

```
#set($amounts = [])
#foreach($transaction in ${ctx.args.transactions})
    #set($attributeValueMap = {})
    $util.qr($attributeValueMap.put(":amount", $util.dynamodb.toNumber($transaction.amount)))
    $util.qr($amounts.add($attributeValueMap))
#end

#set($savingAccountTransactUpdateItems = [])
#set($index = 0)
#foreach($transaction in ${ctx.args.transactions})
    #set($keyMap = {})
    $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($transaction.savingAccountNumber)))
    #set($update = {})
    $util.qr($update.put("expression", "SET balance = balance - :amount"))
    $util.qr($update.put("expressionValues", $amounts[$index]))
    #set($index = $index + 1)
    #set($savingAccountTransactUpdateItem = {"table": "savingAccounts",
        "operation": "UpdateItem",
        "key": $keyMap,
        "update": $update})
    $util.qr($savingAccountTransactUpdateItems.add($savingAccountTransactUpdateItem))
#end

#set($checkingAccountTransactUpdateItems = [])
#set($index = 0)
#foreach($transaction in ${ctx.args.transactions})
    #set($keyMap = {})
    $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($transaction.checkingAccountNumber)))
    #set($update = {})
    $util.qr($update.put("expression", "SET balance = balance + :amount"))
    $util.qr($update.put("expressionValues", $amounts[$index]))
    #set($index = $index + 1)
    #set($checkingAccountTransactUpdateItem = {"table": "checkingAccounts",
        "operation": "UpdateItem",
        "key": $keyMap,
        "update": $update})
    $util.qr($checkingAccountTransactUpdateItems.add($checkingAccountTransactUpdateItem))
#end

#set($transactionHistoryTransactPutItems = [])
#foreach($transaction in ${ctx.args.transactions})
    #set($keyMap = {})
    $util.qr($keyMap.put("transactionId", $util.dynamodb.toString(${utils.autoId()})))
    #set($attributeValues = {})
    $util.qr($attributeValues.put("from", $util.dynamodb.toString($transaction.savingAccountNumber)))
    $util.qr($attributeValues.put("to", $util.dynamodb.toString($transaction.checkingAccountNumber)))
    $util.qr($attributeValues.put("amount", $util.dynamodb.toNumber($transaction.amount)))
    #set($transactionHistoryTransactPutItem = {"table": "transactionHistory",
        "operation": "PutItem",
        "key": $keyMap,
        "attributeValues": $attributeValues})
    $util.qr($transactionHistoryTransactPutItems.add($transactionHistoryTransactPutItem))
#end

#set($transactItems = [])
$util.qr($transactItems.addAll($savingAccountTransactUpdateItems))
$util.qr($transactItems.addAll($checkingAccountTransactUpdateItems))
$util.qr($transactItems.addAll($transactionHistoryTransactPutItems))

{
    "version" : "2018-05-29",
    "operation" : "TransactWriteItems",
    "transactItems" : $util.toJson($transactItems)
}
```

Wir werden drei Banktransaktionen in einem einzigen `TransactWriteItems`-Vorgang durchführen. Verwenden Sie die folgende **Vorlage für die Zuordnung von Antworten**:

```
#if ($ctx.error)
    $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons)
#end

#set($savingAccounts = [])
#foreach($index in [0..2])
    $util.qr($savingAccounts.add(${ctx.result.keys[$index]}))
#end

#set($checkingAccounts = [])
#foreach($index in [3..5])
    $util.qr($checkingAccounts.add(${ctx.result.keys[$index]}))
#end

#set($transactionHistory = [])
#foreach($index in [6..8])
    $util.qr($transactionHistory.add(${ctx.result.keys[$index]}))
#end

#set($transactionResult = {})
$util.qr($transactionResult.put('savingAccounts', $savingAccounts))
$util.qr($transactionResult.put('checkingAccounts', $checkingAccounts))
$util.qr($transactionResult.put('transactionHistory', $transactionHistory))

$util.toJson($transactionResult)
```

Navigieren Sie nun zum Abschnitt **Queries (Abfragen)** der AWS AppSync -Konsole, und führen Sie die **transferMoney**-Mutation wie folgt aus:

```
mutation write {
  transferMoney(
    transactions: [
      {savingAccountNumber: "1", checkingAccountNumber: "1", amount: 7.5},
      {savingAccountNumber: "2", checkingAccountNumber: "2", amount: 6.0},
      {savingAccountNumber: "3", checkingAccountNumber: "3", amount: 3.3}
    ]) {
    savingAccounts {
      accountNumber
    }
    checkingAccounts {
      accountNumber
    }
    transactionHistory {
      transactionId
    }
  }
}
```

Wir haben zwei Banktransaktionen in einer Mutation gesendet. **Verwenden Sie die DynamoDB-Konsole, um zu überprüfen, ob Daten in den Tabellen **SavingAccounts, **checkingAccounts**** und TransactionHistory angezeigt werden.**

### TransactGetItems - Konten abrufen
<a name="transactgetitems-retrieve-accounts"></a>

Um die Details aus dem Sparkonto und dem Girokonto in einer einzigen Transaktionsanforderung abzurufen, hängen wir einen Resolver an die `Query.getAccounts`-GraphQL-Operation in unserem Schema an. Wählen Sie **Anhängen**, gehen Sie zu VTL Unit Resolvers und wählen Sie dann auf dem nächsten Bildschirm dieselbe `TransactTutorial` Datenquelle aus, die Sie zu Beginn des Tutorials erstellt haben. Konfigurieren Sie die Vorlagen wie folgt:

 **Zuweisungsvorlage für Anforderungen** 

```
#set($savingAccountsTransactGets = [])
#foreach($savingAccountNumber in ${ctx.args.savingAccountNumbers})
    #set($savingAccountKey = {})
    $util.qr($savingAccountKey.put("accountNumber", $util.dynamodb.toString($savingAccountNumber)))
    #set($savingAccountTransactGet = {"table": "savingAccounts", "key": $savingAccountKey})
    $util.qr($savingAccountsTransactGets.add($savingAccountTransactGet))
#end

#set($checkingAccountsTransactGets = [])
#foreach($checkingAccountNumber in ${ctx.args.checkingAccountNumbers})
    #set($checkingAccountKey = {})
    $util.qr($checkingAccountKey.put("accountNumber", $util.dynamodb.toString($checkingAccountNumber)))
    #set($checkingAccountTransactGet = {"table": "checkingAccounts", "key": $checkingAccountKey})
    $util.qr($checkingAccountsTransactGets.add($checkingAccountTransactGet))
#end

#set($transactItems = [])
$util.qr($transactItems.addAll($savingAccountsTransactGets))
$util.qr($transactItems.addAll($checkingAccountsTransactGets))

{
    "version" : "2018-05-29",
    "operation" : "TransactGetItems",
    "transactItems" : $util.toJson($transactItems)
}
```

 **Zuweisungsvorlage für Antworten** 

```
#if ($ctx.error)
    $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons)
#end

#set($savingAccounts = [])
#foreach($index in [0..2])
    $util.qr($savingAccounts.add(${ctx.result.items[$index]}))
#end

#set($checkingAccounts = [])
#foreach($index in [3..4])
    $util.qr($checkingAccounts.add($ctx.result.items[$index]))
#end

#set($transactionResult = {})
$util.qr($transactionResult.put('savingAccounts', $savingAccounts))
$util.qr($transactionResult.put('checkingAccounts', $checkingAccounts))

$util.toJson($transactionResult)
```

Speichern Sie den Resolver und navigieren Sie zu den **Query-Abschnitten** der Konsole. AWS AppSync Um die Sparkonten und die Girokonten abzurufen, führen Sie die folgende Abfrage aus:

```
query getAccounts {
  getAccounts(
    savingAccountNumbers: ["1", "2", "3"],
    checkingAccountNumbers: ["1", "2"]
  ) {
    savingAccounts {
      accountNumber
      username
      balance
    }
    checkingAccounts {
      accountNumber
      username
      balance
    }
  }
}
```

Wir haben erfolgreich die Verwendung von DynamoDB-Transaktionen unter Verwendung von demonstriert. AWS AppSync