

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

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

Sebagai contoh situasi di mana Amazon DynamoDB transactions dapat berguna, pertimbangkan contoh aplikasi Java untuk marketplace online ini.

Aplikasi ini memiliki tiga tabel DynamoDB di backend:
+ `Customers` — Tabel ini menyimpan detail tentang pelanggan marketplace. Kunci primernya adalah pengidentifikasi unik `CustomerId`.
+ `ProductCatalog` — Tabel ini menyimpan detail seperti harga dan ketersediaan produk yang dijual di marketplace. Kunci primernya adalah pengidentifikasi unik `ProductId`.
+ `Orders` — Tabel ini menyimpan detail pesanan dari marketplace. Kunci primernya adalah pengidentifikasi unik `OrderId`.

## Membuat pesanan
<a name="transaction-example-write-order"></a>

Potongan kode berikut menggambarkan cara menggunakan DynamoDB transaction untuk mengoordinasikan beberapa langkah yang diperlukan untuk membuat dan memproses pesanan. Menggunakan satu all-or-nothing operasi memastikan bahwa jika ada bagian dari transaksi yang gagal, tidak ada tindakan dalam transaksi yang dijalankan dan tidak ada perubahan yang dilakukan.

Dalam contoh ini, Anda menyiapkan pesanan dari pelanggan yang `customerId` adalah `09e8e9c8-ec48`. Anda kemudian menjalankannya sebagai satu transaksi menggunakan alur kerja pemrosesan pesanan sederhana berikut:

1. Tentukan apakah ID pelanggan valid.

1. Pastikan produk `IN_STOCK`, dan perbarui status produk menjadi `SOLD`.

1. Pastikan pesanan belum ada, lalu buat pesanan.

### Memvalidasi pelanggan
<a name="transaction-example-order-part-a"></a>

Pertama, tentukan tindakan untuk memverifikasi bahwa pelanggan dengan `customerId` sama dengan `09e8e9c8-ec48` ada di tabel pelanggan.

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

### Memperbarui status produk
<a name="transaction-example-order-part-b"></a>

Selanjutnya, tentukan tindakan untuk memperbarui status produk menjadi `SOLD` jika kondisi status produk saat ini diatur ke `IN_STOCK` `true`. Mengatur parameter `ReturnValuesOnConditionCheckFailure` akan mengembalikan item jika atribut status produk item tidak sama dengan `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);
```

### Membuat pesanan
<a name="transaction-example-order-part-c"></a>

Terakhir, buat pesanan selama pesanan dengan `OrderId` tersebut belum ada.

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

### Menjalankan transaksi
<a name="transaction-example-order-part-d"></a>

Contoh berikut menggambarkan bagaimana menjalankan tindakan yang didefinisikan sebelumnya sebagai all-or-nothing operasi tunggal.

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

## Membaca detail pesanan
<a name="transaction-example-read-order"></a>

Contoh berikut menunjukkan cara membaca pesanan yang telah selesai secara transaksional di seluruh tabel `Orders` dan `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());
}
```