调用一次 AmazonDynamoDB.transactWriteItems 方法以在一个或多个表中保存和删除对象。
有关事务特定的异常列表,请参阅 TransactWriteItems 错误。
有关 DynamoDB 事务和提供的原子性、一致性、隔离性和持久性 (ACID) 保证的更多信息,请参阅 Amazon DynamoDB 事务。
注意
该方法不支持:
乐观锁(使用版本号)。
DynamoDBMapperConfig.SaveBehavior。
以下 Java 代码段以事务方式将新项目分别写入到 Forum 和 Thread 表中。
Threads3ForumThread =new Thread();
s3ForumThread.forumName ="S3 Forum";
s3ForumThread.subject ="Sample Subject 1";
s3ForumThread.message ="Sample Question 1";
Forums3Forum =new Forum();
s3Forum.name ="S3 Forum";
s3Forum.category ="Amazon Web Services";
s3Forum.threads =1;
TransactionWriteRequesttransactionWriteRequest =new TransactionWriteRequest();
transactionWriteRequest.addPut(s3Forum);
transactionWriteRequest.addPut(s3ForumThread);
mapper.transactionWrite(transactionWriteRequest);
事务示例
验证客户
首先,定义一个操作,以验证 customerId 等于 09e8e9c8-ec48 的客户在 customers 表中存在。
final String CUSTOMER_TABLE_NAME = "Customers";
final String CUSTOMER_PARTITION_KEY = "CustomerId";
final String customerId = "09e8e9c8-ec48";
final HashMap
customerItemKey = new HashMap<>(); customerItemKey.put(CUSTOMER_PARTITION_KEY, new AttributeValue(customerId));
ConditionCheck checkItem = new ConditionCheck()
.withTableName(CUSTOMER_TABLE_NAME)
.withKey(customerItemKey)
.withConditionExpression("attribute_exists(" + CUSTOMER_PARTITION_KEY + ")");
更新产品状态
接下来,定义一个操作以将产品状态更新为 SOLD(如果产品状态当前设置为 IN_STOCK 的条件为 true)。如果项目的产品状态属性不等于 IN_STOCK,设置 ReturnValuesOnConditionCheckFailure 参数将返回项目。
final String PRODUCT_TABLE_NAME = "ProductCatalog";
final String PRODUCT_PARTITION_KEY = "ProductId";
HashMap
productItemKey = new HashMap<>(); productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));
Map
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);
创建订单
最后,只要具有 OrderId 的订单尚未存在,就创建此订单。
final String ORDER_PARTITION_KEY = "OrderId";
final String ORDER_TABLE_NAME = "Orders";
HashMap
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 + ")");
执行事务
以下代码段阐述如何执行之前定义为单个“要么全有要么全无”操作的操作。
Collection
actions = Arrays.asList( new TransactWriteItem().withConditionCheck(checkCustomerValid),
new TransactWriteItem().withPut(createOrder),
new TransactWriteItem().withUpdate(markItemSold));
TransactWriteItemsRequest placeOrderTransaction = new TransactWriteItemsRequest()
.withTransactItems(actions)
.withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);
// Execute 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());
}
读取订单详细信息
以下代码段说明如何跨 Orders 和 ProductCatalog 表事务性读取已完成的订单。
HashMap
productItemKey = new HashMap<>(); productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));
HashMap
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
getActions = Arrays.asList( new TransactGetItem().withGet(readProductSold),
new TransactGetItem().withGet(readCreatedOrder));
TransactGetItemsRequest readCompletedOrder = new TransactGetItemsRequest()
.withTransactItems(getActions)
.withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);
// Execute 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());
}