DynamoDB UpdateItem di Java (AWS SDK v2)

Update-nya sendiri adalah satu panggilan builder. Yang menghabiskan waktu developer Java adalah semua hal di sekitarnya: objek respons yang tak pernah mengembalikan null, hierarki exception di mana kegagalan yang menarik adalah subclass dari yang mungkin sudah Anda tangkap, dan client tingkat tinggi yang sama sekali tak bisa menyatakan operasi ini.

Kode

import java.util.HashMap;
import java.util.Map;

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ReturnValue;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse;

public class UpdateItemExample {
    public static void main(String[] args) {
        try (DynamoDbClient ddb = DynamoDbClient.builder()
                .region(Region.US_EAST_1)
                .build()) {

            Map<String, AttributeValue> key = new HashMap<>();
            key.put("Artist", AttributeValue.builder().s("Arturo Sandoval").build());
            key.put("SongTitle", AttributeValue.builder().s("Cubano Chant").build());

            Map<String, String> names = new HashMap<>();
            names.put("#upd0", "Genre");
            names.put("#upd1", "Year");
            names.put("#upd2", "Awards");

            Map<String, AttributeValue> values = new HashMap<>();
            values.put(":updValue0", AttributeValue.builder().s("Latin Jazz").build());
            values.put(":updValue1", AttributeValue.builder().n("1994").build());
            values.put(":updValue2", AttributeValue.builder().n("1").build());

            UpdateItemRequest request = UpdateItemRequest.builder()
                    .tableName("Music")
                    .key(key)
                    .updateExpression("SET #upd0 = :updValue0, #upd1 = :updValue1 ADD #upd2 :updValue2")
                    .expressionAttributeNames(names)
                    .expressionAttributeValues(values)
                    .returnValues(ReturnValue.ALL_NEW)
                    .build();

            UpdateItemResponse response = ddb.updateItem(request);
            System.out.println(response.attributes()); // the item after the update
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
        }
    }
}

Penjelasan

  • AttributeValue.builder().n("1994") menerima sebuah String, begitu pula AttributeValue.fromN("1994") yang lebih ringkas. Tak ada overload n(int), karena angka DynamoDB menampung 38 digit signifikan dan tak ada primitif Java yang bisa. Saat membacanya kembali, attributes().get("Awards").n() juga sebuah String; accessor untuk tipe yang salah mengembalikan null alih-alih melempar error, jadi .s() pada sebuah angka adalah null yang senyap, dan .type() memberi tahu Anda yang mana yang terisi.

  • response.attributes() tak pernah mengembalikan null. Dengan ReturnValue.NONE ia mengembalikan sebuah DefaultSdkAutoConstructMap yang kosong tapi bukan null, jadi pemeriksaan null tak pernah menyala dan pemeriksaan isEmpty() tak bisa membedakan "layanan tidak mengirim apa-apa" dari "item-nya tak punya atribut". hasAttributes() yang dihasilkan adalah accessor yang tahu bedanya. Setiap member koleksi di SDK ini punya satu.

  • Builder-nya memeriksa tipe segalanya kecuali bagian yang penting. updateExpression(String) menerima string apa pun; kompiler tak bisa membedakan SET dari salah ketik, jadi kesalahan expression menjadi 400 saat runtime. ADD #upd2 :updValue2 adalah increment atomiknya, conditionExpression berisi attribute_exists(Artist) membuat panggilan itu hanya-memperbarui, dan tata bahasanya ada di update expression.

  • Utamakan expression daripada map attributeUpdates yang legacy. Contoh-contoh lama masih menampilkannya; ia tak bisa menyatakan beberapa jenis klausa, alias, atau sebuah kondisi dalam satu request.

  • getMessage() bukan pesan dari layanan. SDK menambahkan detail transportnya sendiri:

    The conditional request failed (Service: DynamoDb, Status Code: 400, Request ID: d99b117c-edd6-4dc9-8d3a-a5fa4fe9666c) (SDK Attempt Count: 1)

    Catat itu kalau Anda ingin request ID untuk keperluan support. Bandingkan pada awsErrorDetails().errorCode() sebagai gantinya, dan pakai awsErrorDetails().errorMessage() saat Anda ingin string mentahnya.

Urutan catch lebih penting dari biasanya di sini

ConditionalCheckFailedException extends DynamoDbException, jadi catch (DynamoDbException e) yang diletakkan lebih dulu menelan satu kegagalan yang hampir pasti ingin Anda cabangkan. Tangkap tipe spesifiknya lebih dulu, dan sekalian ambil item-nya:

} catch (ConditionalCheckFailedException e) {
    // with .returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
    if (e.hasItem()) {
        Map<String, AttributeValue> loser = e.item();  // the item as it actually was
    }
} catch (DynamoDbException e) {
    // everything else
}

e.retryable() bernilai false pada yang satu ini, dan itu benar: mencoba ulang kondisi yang gagal hanya akan gagal lagi.

Ketimpangan yang perlu diingat adalah bahwa ValidationException tak punya kelas di SDK ini. Telusuri dynamodb-2.35.9.jar dan tak ada apa pun untuk ditangkap. Sebuah reserved word, expression yang bentuknya salah, key yang tak lengkap: semuanya datang sebagai DynamoDbException biasa yang awsErrorDetails().errorCode()-nya kebetulan berbunyi ValidationException. Dalam bahasa bertipe statis itu celah yang mengganggu, dan artinya kesalahan expression menjadi perbandingan string saat runtime.

Itulah sebabnya reserved word DynamoDB layak diperiksa sebelum Anda merilis alih-alih sesudahnya: daftarnya mencapai 573 entri dan mencakup Year, Name dan Status, yang tak satu pun terlihat berbahaya di dalam sebuah bean Java. Untuk menjelajahi tabel mentahnya alih-alih pemetaan bean di atasnya, unduh DynoTable.

Enhanced client tak bisa menyatakan ini

Kalau sisa akses data Anda melewati DynamoDbEnhancedClient dan bean beranotasi, operasi inilah yang menjatuhkan Anda kembali ke DynamoDbClient. Refleksi atas UpdateItemEnhancedRequest.Builder memunculkan item, conditionExpression, ignoreNulls, ignoreNullsMode, returnValues, returnValuesOnConditionCheckFailure, returnConsumedCapacity dan returnItemCollectionMetrics. Tak ada metode yang menerima sebuah update expression.

Konsekuensi praktisnya adalah counter atomik. ADD #upd2 :updValue2 menaikkan Awards di sisi server tanpa pembacaan lebih dulu; enhanced client memberi Anda bean terpetakan dan ignoreNulls untuk menentukan apakah field yang tak ada dihapus, dan tak ada yang terkompilasi menjadi ADD. Read-modify-write lewat sebuah bean adalah balapan lost-update di bawah konkurensi, dan itulah persis yang dihindari cuplikan di halaman ini.

Contoh terkait

Referensi

Terakhir diverifikasi 2026-07-28 terhadap dokumentasi resmi AWS yang ditautkan di atas.

Bekerja dengan DynamoDB tanpa Console

Klien desktop DynamoDB yang cepat dan menjalankan SQL sungguhan yang tidak bisa dijalankan DynamoDB — JOINs, GROUP BY, agregasi — dengan editing visual dan agen AI pada kunci Bedrock milik Anda sendiri.

Uji coba gratis 30 hari, tanpa kartu kredit — lalu paket Free tanpa batas waktu.