Esempio di transazioni di DynamoDB - Amazon DynamoDB

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Esempio di transazioni di DynamoDB

Come esempio di una situazione in cui le transazioni Amazon DynamoDB possono essere utili, si consideri questa applicazione Java di esempio per un marketplace online.

L'applicazione ha tre tabelle DynamoDB nel backend:

  • Customers: questa tabella archivia i dettagli sui clienti del marketplace. La sua chiave primaria è un identificatore univoco CustomerId.

  • ProductCatalog: questa tabella archivia dettagli quali prezzo e disponibilità dei prodotti in vendita nel marketplace. La sua chiave primaria è un identificatore univoco ProductId.

  • Orders: questa tabella archivia i dettagli sugli ordini del marketplace. La sua chiave primaria è un identificatore univoco OrderId.

Come effettuare un ordine

I seguenti frammenti di codice illustrano come utilizzare le transazioni DynamoDB per coordinare i vari passaggi necessari per creare ed elaborare un ordine. L'utilizzo di una singola operazione di tipo "tutto o niente" garantisce che se una parte della transazione non riesce, non vengono eseguite operazioni nella transazione e non vengono apportate modifiche.

In questo esempio, si configura un ordine da un cliente il cui customerId è 09e8e9c8-ec48. Si esegue quindi come una singola transazione utilizzando il seguente flusso di lavoro semplice di elaborazione degli ordini:

  1. Determinare che l'ID cliente sia valido.

  2. Assicurati che il prodotto sia IN_STOCK e aggiornare lo stato del prodotto in SOLD.

  3. Assicurati che l'ordine non esista già e creare l'ordine.

Convalida del cliente

Per prima cosa, definire un'azione per verificare che un cliente con customerId uguale a 09e8e9c8-ec48 esista nella tabella dei clienti.

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 + ")");

Aggiornamento dello stato dei prodotti

Quindi, definire un'operazione per aggiornare lo stato del prodotto in SOLD se la condizione in cui lo stato del prodotto è attualmente impostato su IN_STOCK è true. La configurazione del parametro ReturnValuesOnConditionCheckFailure restituisce l'elemento se l'attributo dello stato del prodotto dell'elemento non era uguale a 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);

Creazione dell'ordine

Infine, creare l'ordine se un ordine con quell'OrderId non esiste già.

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 + ")");

Esecuzione della transazione

L'esempio seguente descrive come eseguire le operazioni definite in precedenza come una singola operazione "tutto o niente".

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

Lettura dei dettagli dell'ordine

L'esempio seguente mostra come leggere l'ordine completato in modo transazionale attraverso le tabelle Orders e 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()); }

Esempi aggiuntivi