

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

# Gunakan ekstensi untuk menyesuaikan operasi DynamoDB Enhanced Client
<a name="ddb-en-client-extensions"></a>

DynamoDB Enhanced Client API mendukung ekstensi plugin yang menyediakan fungsionalitas di luar operasi pemetaan. Ekstensi menggunakan dua metode hook untuk memodifikasi data selama operasi baca dan tulis:
+ `beforeWrite()`- Memodifikasi operasi tulis sebelum itu terjadi
+ `afterRead()`- Memodifikasi hasil operasi baca setelah itu terjadi

Beberapa operasi (seperti pembaruan item) melakukan penulisan dan kemudian membaca, sehingga kedua metode kait dipanggil.

## Bagaimana ekstensi dimuat
<a name="ddb-en-client-extensions-loading"></a>

Ekstensi dimuat dalam urutan yang Anda tentukan di pembuat klien yang disempurnakan. Urutan pemuatan dapat menjadi penting karena satu ekstensi dapat bertindak berdasarkan nilai yang telah diubah oleh ekstensi sebelumnya.

Secara default, klien yang disempurnakan memuat dua ekstensi:
+ `[VersionedRecordExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/VersionedRecordExtension.html)`- Memberikan penguncian optimis
+ `[AtomicCounterExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/AtomicCounterExtension.html)`- Secara otomatis menambah atribut penghitung

Anda dapat mengganti perilaku default dengan pembuat klien yang disempurnakan dan memuat ekstensi apa pun. Anda juga dapat menentukan none jika Anda tidak ingin ekstensi default.

**penting**  
Jika Anda memuat ekstensi Anda sendiri, klien yang disempurnakan tidak memuat ekstensi default apa pun. Jika Anda menginginkan perilaku yang disediakan oleh salah satu ekstensi default, Anda perlu menambahkannya secara eksplisit ke daftar ekstensi.

Contoh berikut menunjukkan cara memuat ekstensi kustom yang `verifyChecksumExtension` dinamai`VersionedRecordExtension`. `AtomicCounterExtension`Tidak dimuat dalam contoh ini.

```
DynamoDbEnhancedClientExtension versionedRecordExtension = VersionedRecordExtension.builder().build();

DynamoDbEnhancedClient enhancedClient = 
    DynamoDbEnhancedClient.builder()
                          .dynamoDbClient(dynamoDbClient)
                          .extensions(versionedRecordExtension, verifyChecksumExtension)
                          .build();
```

## Detail dan konfigurasi ekstensi yang tersedia
<a name="ddb-en-client-extensions-details"></a>

Bagian berikut memberikan informasi rinci tentang setiap ekstensi yang tersedia di SDK.

### Terapkan penguncian optimis dengan `VersionedRecordExtension`
<a name="ddb-en-client-extensions-VRE"></a>

`VersionedRecordExtension`Ekstensi ini memberikan penguncian optimis dengan menambah dan melacak nomor versi item saat item ditulis ke database. Kondisi ditambahkan ke setiap penulisan yang menyebabkan penulisan gagal jika nomor versi item tetap yang sebenarnya tidak cocok dengan nilai yang terakhir dibaca aplikasi.

#### Konfigurasi
<a name="ddb-en-client-extensions-VRE-conf"></a>

Untuk menentukan atribut mana yang akan digunakan untuk melacak nomor versi item, beri tag atribut numerik dalam skema tabel.

Cuplikan berikut menentukan bahwa `version` atribut harus menyimpan nomor versi item.

```
    @DynamoDbVersionAttribute
    public Integer getVersion() {...};
    public void setVersion(Integer version) {...};
```

Pendekatan skema tabel statis setara ditunjukkan dalam cuplikan berikut.

```
    .addAttribute(Integer.class, a -> a.name("version")
                                       .getter(Customer::getVersion)
                                       .setter(Customer::setVersion)
                                        // Apply the 'version' tag to the attribute.
                                       .tags(VersionedRecordExtension.AttributeTags.versionAttribute())
```

#### Cara kerjanya
<a name="ddb-en-client-extensions-VRE-how-it-works"></a>

Penguncian optimis dengan `VersionedRecordExtension` memiliki dampak berikut pada ini `DynamoDbEnhancedClient` dan `DynamoDbTable` metode:

**`putItem`**  
Item baru diberi nilai versi awal 0. Ini dapat dikonfigurasi dengan`@DynamoDbVersionAttribute(startAt = X)`.

**`updateItem`**  
Jika Anda mengambil item, memperbarui satu atau beberapa propertinya, dan mencoba menyimpan perubahan, operasi hanya berhasil jika nomor versi di sisi klien dan sisi server cocok.  
Jika berhasil, nomor versi secara otomatis bertambah 1. Ini dapat dikonfigurasi dengan`@DynamoDbVersionAttribute(incrementBy = X)`.

**`deleteItem`**  
`DynamoDbVersionAttribute`Anotasi tidak berpengaruh. Anda harus menambahkan ekspresi kondisi secara manual saat menghapus item.  
Contoh berikut menambahkan ekspresi bersyarat untuk memastikan bahwa item yang dihapus adalah item yang telah dibaca. Dalam contoh berikut `recordVersion` adalah atribut kacang yang dianotasi dengan. `@DynamoDbVersionAttribute`  

```
// 1. Read the item and get its current version.
Customer item = customerTable.getItem(Key.builder().partitionValue("someId").build());
// `recordVersion` is the bean's attribute that is annotated with `@DynamoDbVersionAttribute`.
AttributeValue currentVersion = item.getRecordVersion();

// 2. Create conditional delete with the `currentVersion` value.
DeleteItemEnhancedRequest deleteItemRequest =
    DeleteItemEnhancedRequest.builder()
       .key(KEY)
       .conditionExpression(Expression.builder()
           .expression("recordVersion = :current_version_value")
           .putExpressionValue(":current_version_value", currentVersion)
           .build()).build();

customerTable.deleteItem(deleteItemRequest);
```

**`transactWriteItems`**  
+ `addPutItem`: Metode ini memiliki perilaku yang sama dengan`putItem`.
+ `addUpdateItem`: Metode ini memiliki perilaku yang sama dengan`updateItem`.
+ `addDeleteItem`: Metode ini memiliki perilaku yang sama dengan`deleteItem`.

**`batchWriteItem`**  
+ `addPutItem`: Metode ini memiliki perilaku yang sama dengan`putItem`.
+ `addDeleteItem`: Metode ini memiliki perilaku yang sama dengan`deleteItem`.

**catatan**  
Tabel global DynamoDB menggunakan rekonsiliasi ['penulis terakhir menang'](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html#V2globaltables_HowItWorks.consistency-modes) antara pembaruan bersamaan, di mana DynamoDB melakukan upaya terbaik untuk menentukan penulis terakhir. Jika Anda menggunakan tabel global, kebijakan 'penulis terakhir menang' ini berarti bahwa strategi penguncian mungkin tidak berfungsi seperti yang diharapkan, karena semua replika pada akhirnya akan bertemu berdasarkan penulisan terakhir yang ditentukan oleh DynamoDB. 

#### Cara menonaktifkan
<a name="ddb-en-client-extensions-VRE-how-to-disable"></a>

Untuk menonaktifkan penguncian optimis, jangan gunakan `@DynamoDbVersionAttribute` anotasi.

### Menerapkan penghitung dengan `AtomicCounterExtension`
<a name="ddb-en-client-extensions-ACE"></a>

`AtomicCounterExtension`Ekstensi menambah atribut numerik yang ditandai setiap kali catatan ditulis ke database. Anda dapat menentukan nilai awal dan kenaikan. Jika tidak ada nilai yang ditentukan, nilai awal diatur ke 0 dan nilai atribut meningkat sebesar 1.

#### Konfigurasi
<a name="ddb-en-client-extensions-ACE-conf"></a>

Untuk menentukan atribut mana yang merupakan penghitung, beri tag atribut tipe `Long` dalam skema tabel.

Cuplikan berikut menunjukkan penggunaan nilai awal dan kenaikan default untuk atribut. `counter`

```
    @DynamoDbAtomicCounter
    public Long getCounter() {...};
    public void setCounter(Long counter) {...};
```

Pendekatan skema tabel statis ditunjukkan dalam cuplikan berikut. Ekstensi penghitung atom menggunakan nilai awal 10 dan menambah nilai sebesar 5 setiap kali catatan ditulis.

```
    .addAttribute(Integer.class, a -> a.name("counter")
                                       .getter(Customer::getCounter)
                                       .setter(Customer::setCounter)
                                        // Apply the 'atomicCounter' tag to the attribute with start and increment values.
                                       .tags(StaticAttributeTags.atomicCounter(10L, 5L))
```

### Tambahkan stempel waktu dengan `AutoGeneratedTimestampRecordExtension`
<a name="ddb-en-client-extensions-AGTE"></a>

`AutoGeneratedTimestampRecordExtension`Ekstensi secara otomatis memperbarui atribut tipe yang ditandai `[Instant](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html)` dengan stempel waktu saat ini setiap kali item berhasil ditulis ke database. Ekstensi ini tidak dimuat secara default.

#### Konfigurasi
<a name="ddb-en-client-extensions-AGTE-conf"></a>

Untuk menentukan atribut mana yang akan diperbarui dengan stempel waktu saat ini, beri tag `Instant` atribut dalam skema tabel.

`lastUpdate`Atribut adalah target perilaku ekstensi dalam cuplikan berikut. Perhatikan persyaratan bahwa atribut harus berupa `Instant` tipe.

```
    @DynamoDbAutoGeneratedTimestampAttribute
    public Instant getLastUpdate() {...}
    public void setLastUpdate(Instant lastUpdate) {...}
```

Pendekatan skema tabel statis setara ditunjukkan dalam cuplikan berikut.

```
     .addAttribute(Instant.class, a -> a.name("lastUpdate")
                                        .getter(Customer::getLastUpdate)
                                        .setter(Customer::setLastUpdate)
                                        // Applying the 'autoGeneratedTimestamp' tag to the attribute.
                                        .tags(AutoGeneratedTimestampRecordExtension.AttributeTags.autoGeneratedTimestampAttribute())
```

### Hasilkan UUID dengan AutoGeneratedUuidExtension
<a name="ddb-en-client-extensions-AGUE"></a>

`AutoGeneratedUuidExtension`Ekstensi menghasilkan UUID unik (Universally Unique Identifier) untuk atribut ketika catatan baru ditulis ke database. Menggunakan metode Java JDK [UUID.randomUUId ()](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--) dan berlaku untuk atribut tipe. `java.lang.String` Ekstensi ini tidak dimuat secara default.

#### Konfigurasi
<a name="ddb-en-client-extensions-AGUE-conf"></a>

`uniqueId`Atribut adalah target perilaku ekstensi dalam cuplikan berikut.

```
    @AutoGeneratedUuidExtension
    public String getUniqueId() {...}
    public void setUniqueId(String uniqueId) {...}
```

Pendekatan skema tabel statis setara ditunjukkan dalam cuplikan berikut.

```
     .addAttribute(String.class, a -> a.name("uniqueId")
                                        .getter(Customer::getUniqueId)
                                        .setter(Customer::setUniqueId)
                                        // Applying the 'autoGeneratedUuid' tag to the attribute.
                                        .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute())
```

Jika Anda ingin ekstensi mengisi UUID hanya untuk `putItem` metode dan bukan untuk `updateItem` metode, tambahkan anotasi [perilaku pembaruan](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html) seperti yang ditunjukkan pada cuplikan berikut.

```
    @AutoGeneratedUuidExtension
    @DynamoDbUpdateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)
    public String getUniqueId() {...}
    public void setUniqueId(String uniqueId) {...}
```

Jika Anda menggunakan pendekatan skema tabel statis, gunakan kode setara berikut.

```
     .addAttribute(String.class, a -> a.name("uniqueId")
                                        .getter(Customer::getUniqueId)
                                        .setter(Customer::setUniqueId)
                                        // Applying the 'autoGeneratedUuid' tag to the attribute.
                                        .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute(),
                                              StaticAttributeTags.updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS))
```

# Contoh ekstensi kustom
<a name="ddb-en-client-extensions-custom"></a>

Anda dapat membuat ekstensi khusus dengan mengimplementasikan `DynamoDbEnhancedClientExtension` antarmuka. Kelas ekstensi kustom berikut menunjukkan `beforeWrite()` metode yang menggunakan ekspresi pembaruan untuk mengatur `registrationDate` atribut jika item dalam database belum memilikinya.

```
public final class CustomExtension implements DynamoDbEnhancedClientExtension {

    // 1. In a custom extension, use an UpdateExpression to define what action to take before
    //    an item is updated.
    @Override
    public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite context) {
        if ( context.operationContext().tableName().equals("Customer")
                && context.operationName().equals(OperationName.UPDATE_ITEM)) {
            return WriteModification.builder()
                    .updateExpression(createUpdateExpression())
                    .build();
        }
        return WriteModification.builder().build();  // Return an "empty" WriteModification instance if the extension should not be applied.
                                                     // In this case, if the code is not updating an item on the Customer table.
    }

    private static UpdateExpression createUpdateExpression() {

        // 2. Use a SetAction, a subclass of UpdateAction, to provide the values in the update.
        SetAction setAction =
                SetAction.builder()
                        .path("registrationDate")
                        .value("if_not_exists(registrationDate, :regValue)")
                        .putExpressionValue(":regValue", AttributeValue.fromS(Instant.now().toString()))
                        .build();
        // 3. Build the UpdateExpression with one or more UpdateAction.
        return UpdateExpression.builder()
                .addAction(setAction)
                .build();
    }
}
```