

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Exemple de transactions DynamoDB
<a name="transaction-example"></a>

A titre d'exemple de situation dans laquelle des transactions Amazon DynamoDB peuvent être utiles, considérez cette application Java pour une place de marché en ligne.

L'application dispose de trois tables DynamoDB dans le backend :
+ `Customers` – Cette table stocke des détails sur les clients de la place de marché. Sa clé primaire est un identifiant unique `CustomerId`.
+ `ProductCatalog` – Ce tableau stocke des détails tels que le prix et la disponibilité des produits en vente sur la place de marché. Sa clé primaire est un identifiant unique `ProductId`.
+ `Orders` – Cette table stocke des détails sur les commandes en provenance de la place de marché. Sa clé primaire est un identifiant unique `OrderId`.

## Passation d'une commande
<a name="transaction-example-write-order"></a>

Les extraits de code suivants montrent comment utiliser des transactions DynamoDB pour coordonner les différentes étapes de la création et du traitement d'une commande. L'utilisation d'une seule all-or-nothing opération garantit qu'en cas d'échec d'une partie de la transaction, aucune action de la transaction n'est exécutée et aucune modification n'est apportée.

Dans cet exemple, vous configurez une commande à partir d'un client dont le `customerId` est `09e8e9c8-ec48`. Vous l'exécutez ensuite en tant que transaction unique à l'aide du simple flux de traitement de commandes suivant :

1. Déterminez si l'ID client est valide.

1. Assurez-vous que l'état du produit est `IN_STOCK` et mettez à jour son état en `SOLD`.

1. Assurez-vous que la commande n'existe pas déjà, puis créez la commande.

### Valider le client
<a name="transaction-example-order-part-a"></a>

Commencez par définir une action pour vérifier qu'un client avec `customerId` égal à `09e8e9c8-ec48` existe dans la table client.

```
final String CUSTOMER_TABLE_NAME = "Customers";
final String CUSTOMER_PARTITION_KEY = "CustomerId";
final String customerId = "09e8e9c8-ec48";
final HashMap<String, AttributeValue> customerItemKey = new HashMap<>();
customerItemKey.put(CUSTOMER_PARTITION_KEY, new AttributeValue(customerId));

ConditionCheck checkCustomerValid = new ConditionCheck()
    .withTableName(CUSTOMER_TABLE_NAME)
    .withKey(customerItemKey)
    .withConditionExpression("attribute_exists(" + CUSTOMER_PARTITION_KEY + ")");
```

### Mettre à jour l'état du produit
<a name="transaction-example-order-part-b"></a>

Ensuite, définissez une action pour mettre à jour l'état du produit sur `SOLD` si la condition que l'état du produit soit actuellement défini sur `IN_STOCK` est `true`. La définition du paramètre `ReturnValuesOnConditionCheckFailure` a pour effet de renvoyer l'article si l'attribut d'état de produit de celui-ci n'est pas `IN_STOCK`.

```
final String PRODUCT_TABLE_NAME = "ProductCatalog";
final String PRODUCT_PARTITION_KEY = "ProductId";
HashMap<String, AttributeValue> productItemKey = new HashMap<>();
productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));

Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
expressionAttributeValues.put(":new_status", new AttributeValue("SOLD"));
expressionAttributeValues.put(":expected_status", new AttributeValue("IN_STOCK"));

Update markItemSold = new Update()
    .withTableName(PRODUCT_TABLE_NAME)
    .withKey(productItemKey)
    .withUpdateExpression("SET ProductStatus = :new_status")
    .withExpressionAttributeValues(expressionAttributeValues)
    .withConditionExpression("ProductStatus = :expected_status")
    .withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD);
```

### Créer la commande
<a name="transaction-example-order-part-c"></a>

Enfin, créez la commande pour autant qu'il n'existe pas de commande avec cet `OrderId`.

```
final String ORDER_PARTITION_KEY = "OrderId";
final String ORDER_TABLE_NAME = "Orders";

HashMap<String, AttributeValue> orderItem = new HashMap<>();
orderItem.put(ORDER_PARTITION_KEY, new AttributeValue(orderId));
orderItem.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));
orderItem.put(CUSTOMER_PARTITION_KEY, new AttributeValue(customerId));
orderItem.put("OrderStatus", new AttributeValue("CONFIRMED"));
orderItem.put("OrderTotal", new AttributeValue("100"));

Put createOrder = new Put()
    .withTableName(ORDER_TABLE_NAME)
    .withItem(orderItem)
    .withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
    .withConditionExpression("attribute_not_exists(" + ORDER_PARTITION_KEY + ")");
```

### Exécuter la transaction
<a name="transaction-example-order-part-d"></a>

L'exemple suivant montre comment exécuter les actions définies précédemment en une seule all-or-nothing opération.

```
    Collection<TransactWriteItem> actions = Arrays.asList(
        new TransactWriteItem().withConditionCheck(checkCustomerValid),
        new TransactWriteItem().withUpdate(markItemSold),
        new TransactWriteItem().withPut(createOrder));

    TransactWriteItemsRequest placeOrderTransaction = new TransactWriteItemsRequest()
        .withTransactItems(actions)
        .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);

    // Run the transaction and process the result.
    try {
        client.transactWriteItems(placeOrderTransaction);
        System.out.println("Transaction Successful");

    } catch (ResourceNotFoundException rnf) {
        System.err.println("One of the table involved in the transaction is not found" + rnf.getMessage());
    } catch (InternalServerErrorException ise) {
        System.err.println("Internal Server Error" + ise.getMessage());
    } catch (TransactionCanceledException tce) {
        System.out.println("Transaction Canceled " + tce.getMessage());
    }
```

## Lecture des détails de la commande
<a name="transaction-example-read-order"></a>

L'exemple suivant montre comment lire la commande terminée de manière transactionnelle dans les tables `Orders` et `ProductCatalog`.

```
HashMap<String, AttributeValue> productItemKey = new HashMap<>();
productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));

HashMap<String, AttributeValue> orderKey = new HashMap<>();
orderKey.put(ORDER_PARTITION_KEY, new AttributeValue(orderId));

Get readProductSold = new Get()
    .withTableName(PRODUCT_TABLE_NAME)
    .withKey(productItemKey);
Get readCreatedOrder = new Get()
    .withTableName(ORDER_TABLE_NAME)
    .withKey(orderKey);

Collection<TransactGetItem> getActions = Arrays.asList(
    new TransactGetItem().withGet(readProductSold),
    new TransactGetItem().withGet(readCreatedOrder));

TransactGetItemsRequest readCompletedOrder = new TransactGetItemsRequest()
    .withTransactItems(getActions)
    .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);

// Run the transaction and process the result.
try {
    TransactGetItemsResult result = client.transactGetItems(readCompletedOrder);
    System.out.println(result.getResponses());
} catch (ResourceNotFoundException rnf) {
    System.err.println("One of the table involved in the transaction is not found" + rnf.getMessage());
} catch (InternalServerErrorException ise) {
    System.err.println("Internal Server Error" + ise.getMessage());
} catch (TransactionCanceledException tce) {
    System.err.println("Transaction Canceled" + tce.getMessage());
}
```