QLDBDriver Amazon untuk Java - Referensi buku masak - Database Buku Besar Amazon Quantum (AmazonQLDB)

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

QLDBDriver Amazon untuk Java - Referensi buku masak

penting

Pemberitahuan akhir dukungan: Pelanggan yang ada akan dapat menggunakan Amazon QLDB hingga akhir dukungan pada 07/31/2025. Untuk detail selengkapnya, lihat Memigrasi QLDB Buku Besar Amazon ke Amazon Aurora Postgre. SQL

Panduan referensi ini menunjukkan kasus penggunaan umum QLDB driver Amazon untuk Java. Ini memberikan contoh kode Java yang menunjukkan bagaimana menggunakan driver untuk menjalankan operasi create, read, update, dan delete (CRUD) dasar. Ini juga mencakup contoh kode untuk memproses data Amazon Ion. Selain itu, panduan ini menyoroti praktik terbaik untuk membuat transaksi idempoten dan menerapkan kendala keunikan.

catatan

Jika berlaku, beberapa kasus penggunaan memiliki contoh kode yang berbeda untuk setiap versi utama QLDB driver yang didukung untuk Java.

Mengimpor driver

Contoh kode berikut mengimpor driver, klien QLDB sesi, paket Amazon Ion, dan dependensi terkait lainnya.

2.x
import com.amazon.ion.IonStruct; import com.amazon.ion.IonSystem; import com.amazon.ion.IonValue; import com.amazon.ion.system.IonSystemBuilder; import software.amazon.awssdk.services.qldbsession.QldbSessionClient; import software.amazon.qldb.QldbDriver; import software.amazon.qldb.Result;
1.x
import com.amazon.ion.IonStruct; import com.amazon.ion.IonSystem; import com.amazon.ion.IonValue; import com.amazon.ion.system.IonSystemBuilder; import com.amazonaws.services.qldbsession.AmazonQLDBSessionClientBuilder; import software.amazon.qldb.PooledQldbDriver; import software.amazon.qldb.Result;

Membuat instantiasi pengemudi

Contoh kode berikut membuat instance driver yang terhubung ke nama buku besar tertentu, dan menggunakan logika coba lagi yang ditentukan dengan batas coba ulang khusus.

catatan

Contoh ini juga membuat instance objek sistem Amazon Ion ()IonSystem. Anda memerlukan objek ini untuk memproses data Ion saat menjalankan beberapa operasi data dalam referensi ini. Untuk mempelajari selengkapnya, lihat Bekerja dengan Amazon Ion.

2.x
QldbDriver qldbDriver = QldbDriver.builder() .ledger("vehicle-registration") .transactionRetryPolicy(RetryPolicy .builder() .maxRetries(3) .build()) .sessionClientBuilder(QldbSessionClient.builder()) .build(); IonSystem SYSTEM = IonSystemBuilder.standard().build();
1.x
PooledQldbDriver qldbDriver = PooledQldbDriver.builder() .withLedger("vehicle-registration") .withRetryLimit(3) .withSessionClientBuilder(AmazonQLDBSessionClientBuilder.standard()) .build(); IonSystem SYSTEM = IonSystemBuilder.standard().build();

Operasi CRUD

QLDBmenjalankan operasi create, read, update, dan delete (CRUD) sebagai bagian dari transaksi.

Awas

Sebagai praktik terbaik, buat transaksi tulis Anda benar-benar idempoten.

Membuat transaksi idempoten

Kami menyarankan Anda membuat transaksi tulis idempoten untuk menghindari efek samping yang tidak terduga dalam kasus percobaan ulang. Transaksi adalah idempoten jika dapat berjalan beberapa kali dan menghasilkan hasil yang identik setiap kali.

Misalnya, pertimbangkan transaksi yang menyisipkan dokumen ke dalam tabel bernamaPerson. Transaksi harus terlebih dahulu memeriksa apakah dokumen sudah ada dalam tabel atau tidak. Tanpa pemeriksaan ini, tabel mungkin berakhir dengan dokumen duplikat.

Misalkan QLDB berhasil melakukan transaksi di sisi server, tetapi klien kehabisan waktu sambil menunggu respons. Jika transaksi tidak idempoten, dokumen yang sama dapat dimasukkan lebih dari sekali dalam kasus percobaan ulang.

Menggunakan indeks untuk menghindari pemindaian tabel penuh

Kami juga menyarankan Anda menjalankan pernyataan dengan klausa WHERE predikat menggunakan operator kesetaraan pada bidang yang diindeks atau ID dokumen; misalnya, atau. WHERE indexedField = 123 WHERE indexedField IN (456, 789) Tanpa pencarian yang diindeks ini, QLDB perlu melakukan pemindaian tabel, yang dapat menyebabkan batas waktu transaksi atau konflik kontrol konkurensi () yang optimis. OCC

Untuk informasi selengkapnya tentang OCC, lihat Model QLDB konkurensi Amazon.

Transaksi yang dibuat secara implisit

QldbDriverMetode.execute menerima fungsi lambda yang menerima instance Executor, yang dapat Anda gunakan untuk menjalankan pernyataan. ExecutorInstance membungkus transaksi yang dibuat secara implisit.

Anda dapat menjalankan pernyataan dalam fungsi lambda dengan menggunakan Executor.execute metode. Pengemudi secara implisit melakukan transaksi saat fungsi lambda kembali.

Bagian berikut menunjukkan cara menjalankan CRUD operasi dasar, menentukan logika coba ulang kustom, dan menerapkan kendala keunikan.

catatan

Jika berlaku, bagian ini memberikan contoh kode pemrosesan data Amazon Ion menggunakan pustaka Ion bawaan dan pustaka mapper Jackson Ion. Untuk mempelajari selengkapnya, lihat Bekerja dengan Amazon Ion.

Membuat tabel

qldbDriver.execute(txn -> { txn.execute("CREATE TABLE Person"); });

Membuat indeks

qldbDriver.execute(txn -> { txn.execute("CREATE INDEX ON Person(GovId)"); });

Membaca dokumen

// Assumes that Person table has documents as follows: // { GovId: "TOYENC486FH", FirstName: "Brent" } qldbDriver.execute(txn -> { Result result = txn.execute("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'"); IonStruct person = (IonStruct) result.iterator().next(); System.out.println(person.get("GovId")); // prints TOYENC486FH System.out.println(person.get("FirstName")); // prints Brent });

Menggunakan parameter kueri

Contoh kode berikut menggunakan parameter query tipe Ion.

qldbDriver.execute(txn -> { Result result = txn.execute("SELECT * FROM Person WHERE GovId = ?", SYSTEM.newString("TOYENC486FH")); IonStruct person = (IonStruct) result.iterator().next(); System.out.println(person.get("GovId")); // prints TOYENC486FH System.out.println(person.get("FirstName")); // prints Brent });

Contoh kode berikut menggunakan beberapa parameter query.

qldbDriver.execute(txn -> { Result result = txn.execute("SELECT * FROM Person WHERE GovId = ? AND FirstName = ?", SYSTEM.newString("TOYENC486FH"), SYSTEM.newString("Brent")); IonStruct person = (IonStruct) result.iterator().next(); System.out.println(person.get("GovId")); // prints TOYENC486FH System.out.println(person.get("FirstName")); // prints Brent });

Contoh kode berikut menggunakan daftar parameter query.

qldbDriver.execute(txn -> { final List<IonValue> parameters = new ArrayList<>(); parameters.add(SYSTEM.newString("TOYENC486FH")); parameters.add(SYSTEM.newString("ROEE1")); parameters.add(SYSTEM.newString("YH844")); Result result = txn.execute("SELECT * FROM Person WHERE GovId IN (?,?,?)", parameters); IonStruct person = (IonStruct) result.iterator().next(); System.out.println(person.get("GovId")); // prints TOYENC486FH System.out.println(person.get("FirstName")); // prints Brent });
// Assumes that Person table has documents as follows: // {GovId: "TOYENC486FH", FirstName: "Brent" } qldbDriver.execute(txn -> { try { Result result = txn.execute("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'"); Person person = MAPPER.readValue(result.iterator().next(), Person.class); System.out.println(person.getFirstName()); // prints Brent System.out.println(person.getGovId()); // prints TOYENC486FH } catch (IOException e) { e.printStackTrace(); } });

Menggunakan parameter kueri

Contoh kode berikut menggunakan parameter query tipe Ion.

qldbDriver.execute(txn -> { try { Result result = txn.execute("SELECT * FROM Person WHERE GovId = ?", MAPPER.writeValueAsIonValue("TOYENC486FH")); Person person = MAPPER.readValue(result.iterator().next(), Person.class); System.out.println(person.getFirstName()); // prints Brent System.out.println(person.getGovId()); // prints TOYENC486FH } catch (IOException e) { e.printStackTrace(); } });

Contoh kode berikut menggunakan beberapa parameter query.

qldbDriver.execute(txn -> { try { Result result = txn.execute("SELECT * FROM Person WHERE GovId = ? AND FirstName = ?", MAPPER.writeValueAsIonValue("TOYENC486FH"), MAPPER.writeValueAsIonValue("Brent")); Person person = MAPPER.readValue(result.iterator().next(), Person.class); System.out.println(person.getFirstName()); // prints Brent System.out.println(person.getGovId()); // prints TOYENC486FH } catch (IOException e) { e.printStackTrace(); } });

Contoh kode berikut menggunakan daftar parameter query.

qldbDriver.execute(txn -> { try { final List<IonValue> parameters = new ArrayList<>(); parameters.add(MAPPER.writeValueAsIonValue("TOYENC486FH")); parameters.add(MAPPER.writeValueAsIonValue("ROEE1")); parameters.add(MAPPER.writeValueAsIonValue("YH844")); Result result = txn.execute("SELECT * FROM Person WHERE GovId IN (?,?,?)", parameters); Person person = MAPPER.readValue(result.iterator().next(), Person.class); System.out.println(person.getFirstName()); // prints Brent System.out.println(person.getGovId()); // prints TOYENC486FH } catch (IOException e) { e.printStackTrace(); } });
catatan

Saat Anda menjalankan kueri tanpa pencarian yang diindeks, itu akan memanggil pemindaian tabel lengkap. Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId, kueri dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.

Menyisipkan dokumen

Contoh kode berikut menyisipkan tipe data Ion.

qldbDriver.execute(txn -> { // Check if a document with GovId:TOYENC486FH exists // This is critical to make this transaction idempotent Result result = txn.execute("SELECT * FROM Person WHERE GovId = ?", SYSTEM.newString("TOYENC486FH")); // Check if there is a result if (!result.iterator().hasNext()) { IonStruct person = SYSTEM.newEmptyStruct(); person.put("GovId").newString("TOYENC486FH"); person.put("FirstName").newString("Brent"); // Insert the document txn.execute("INSERT INTO Person ?", person); } });

Contoh kode berikut menyisipkan tipe data Ion.

qldbDriver.execute(txn -> { try { // Check if a document with GovId:TOYENC486FH exists // This is critical to make this transaction idempotent Result result = txn.execute("SELECT * FROM Person WHERE GovId = ?", MAPPER.writeValueAsIonValue("TOYENC486FH")); // Check if there is a result if (!result.iterator().hasNext()) { // Insert the document txn.execute("INSERT INTO Person ?", MAPPER.writeValueAsIonValue(new Person("Brent", "TOYENC486FH"))); } } catch (IOException e) { e.printStackTrace(); } });

Transaksi ini memasukkan dokumen ke dalam Person tabel. Sebelum memasukkan, pertama-tama memeriksa apakah dokumen sudah ada di tabel. Pemeriksaan ini membuat transaksi idempoten di alam. Bahkan jika Anda menjalankan transaksi ini beberapa kali, itu tidak akan menyebabkan efek samping yang tidak diinginkan.

catatan

Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.

Menyisipkan beberapa dokumen dalam satu pernyataan

Untuk menyisipkan beberapa dokumen dengan menggunakan satu INSERT pernyataan, Anda dapat meneruskan parameter tipe IonList(secara eksplisit dilemparkan sebagai anIonValue) ke pernyataan sebagai berikut.

// people is an IonList explicitly cast as an IonValue txn.execute("INSERT INTO People ?", (IonValue) people);

Anda tidak melampirkan variabel placeholder (?) dalam tanda kurung sudut ganda (<<...>>) saat melewati sebuah. IonList Dalam pernyataan PartiQL manual, tanda kurung sudut ganda menunjukkan koleksi tidak berurutan yang dikenal sebagai tas.

TransactionExecutorMetode.execute kelebihan beban. Ia menerima sejumlah variabel IonValue argumen (varargs), atau argumen tunggal. List<IonValue> Dalam ion-java, IonList diimplementasikan sebagai. List<IonValue>

Java default untuk implementasi metode yang paling spesifik ketika Anda memanggil metode kelebihan beban. Dalam hal ini, ketika Anda melewatkan IonList parameter, itu default ke metode yang membutuhkan. List<IonValue> Ketika dipanggil, implementasi metode ini melewati IonValue elemen daftar sebagai nilai yang berbeda. Jadi, untuk memanggil metode varargs sebagai gantinya, Anda harus secara eksplisit melemparkan parameter sebagai. IonList IonValue

Memperbarui dokumen

qldbDriver.execute(txn -> { final List<IonValue> parameters = new ArrayList<>(); parameters.add(SYSTEM.newString("John")); parameters.add(SYSTEM.newString("TOYENC486FH")); txn.execute("UPDATE Person SET FirstName = ? WHERE GovId = ?", parameters); });
qldbDriver.execute(txn -> { try { final List<IonValue> parameters = new ArrayList<>(); parameters.add(MAPPER.writeValueAsIonValue("John")); parameters.add(MAPPER.writeValueAsIonValue("TOYENC486FH")); txn.execute("UPDATE Person SET FirstName = ? WHERE GovId = ?", parameters); } catch (IOException e) { e.printStackTrace(); } });
catatan

Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.

Menghapus dokumen

qldbDriver.execute(txn -> { txn.execute("DELETE FROM Person WHERE GovId = ?", SYSTEM.newString("TOYENC486FH")); });
qldbDriver.execute(txn -> { try { txn.execute("DELETE FROM Person WHERE GovId = ?", MAPPER.writeValueAsIonValue("TOYENC486FH")); } catch (IOException e) { e.printStackTrace(); } });
catatan

Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.

Menjalankan beberapa pernyataan dalam transaksi

// This code snippet is intentionally trivial. In reality you wouldn't do this because you'd // set your UPDATE to filter on vin and insured, and check if you updated something or not. public static boolean InsureCar(QldbDriver qldbDriver, final String vin) { final IonSystem ionSystem = IonSystemBuilder.standard().build(); final IonString ionVin = ionSystem.newString(vin); return qldbDriver.execute(txn -> { Result result = txn.execute( "SELECT insured FROM Vehicles WHERE vin = ? AND insured = FALSE", ionVin); if (!result.isEmpty()) { txn.execute("UPDATE Vehicles SET insured = TRUE WHERE vin = ?", ionVin); return true; } return false; }); }

Logika coba lagi

executeMetode pengemudi memiliki mekanisme coba ulang bawaan yang mencoba ulang transaksi jika terjadi pengecualian yang dapat dicoba ulang (seperti batas waktu atau konflik). OCC

2.x

Jumlah maksimum upaya coba lagi dan strategi backoff dapat dikonfigurasi.

Batas coba lagi default adalah4, dan strategi backoff default adalah. DefaultQldbTransactionBackoffStrategy Anda dapat mengatur konfigurasi coba lagi per instance driver dan juga per transaksi dengan menggunakan instance. RetryPolicy

Contoh kode berikut menentukan logika coba lagi dengan batas coba ulang khusus dan strategi backoff khusus untuk instance driver.

public void retry() { QldbDriver qldbDriver = QldbDriver.builder() .ledger("vehicle-registration") .transactionRetryPolicy(RetryPolicy.builder() .maxRetries(2) .backoffStrategy(new CustomBackOffStrategy()).build()) .sessionClientBuilder(QldbSessionClient.builder()) .build(); } private class CustomBackOffStrategy implements BackoffStrategy { @Override public Duration calculateDelay(RetryPolicyContext retryPolicyContext) { return Duration.ofMillis(1000 * retryPolicyContext.retriesAttempted()); } }

Contoh kode berikut menentukan logika coba lagi dengan batas coba ulang kustom dan strategi backoff khusus untuk transaksi tertentu. Konfigurasi ini untuk execute mengganti logika coba lagi yang disetel untuk instance driver.

public void retry() { Result result = qldbDriver.execute(txn -> { txn.execute("SELECT * FROM Person WHERE GovId = ?", SYSTEM.newString("TOYENC486FH")); }, RetryPolicy.builder() .maxRetries(2) .backoffStrategy(new CustomBackOffStrategy()) .build()); } private class CustomBackOffStrategy implements BackoffStrategy { // Configuring a custom backoff which increases delay by 1s for each attempt. @Override public Duration calculateDelay(RetryPolicyContext retryPolicyContext) { return Duration.ofMillis(1000 * retryPolicyContext.retriesAttempted()); } }
1.x

Jumlah maksimum upaya coba lagi dapat dikonfigurasi. Anda dapat mengonfigurasi batas coba lagi dengan menyetel retryLimit properti saat menginisialisasiPooledQldbDriver.

Batas coba ulang default adalah4.

Menerapkan kendala keunikan

QLDBtidak mendukung indeks unik, tetapi Anda dapat menerapkan perilaku ini di aplikasi Anda.

Misalkan Anda ingin menerapkan kendala keunikan pada GovId bidang dalam tabel. Person Untuk melakukan ini, Anda dapat menulis transaksi yang melakukan hal berikut:

  1. Tegaskan bahwa tabel tidak memiliki dokumen yang ada dengan yang ditentukanGovId.

  2. Masukkan dokumen jika pernyataan lolos.

Jika transaksi yang bersaing secara bersamaan melewati pernyataan, hanya satu transaksi yang akan berhasil dilakukan. Transaksi lainnya akan gagal dengan pengecualian OCC konflik.

Contoh kode berikut menunjukkan bagaimana menerapkan logika kendala keunikan ini.

qldbDriver.execute(txn -> { Result result = txn.execute("SELECT * FROM Person WHERE GovId = ?", SYSTEM.newString("TOYENC486FH")); // Check if there is a result if (!result.iterator().hasNext()) { IonStruct person = SYSTEM.newEmptyStruct(); person.put("GovId").newString("TOYENC486FH"); person.put("FirstName").newString("Brent"); // Insert the document txn.execute("INSERT INTO Person ?", person); } });
catatan

Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.

Bekerja dengan Amazon Ion

Ada beberapa cara untuk memproses data Amazon Ion diQLDB. Anda dapat menggunakan metode bawaan dari perpustakaan Ion untuk membuat dan memodifikasi dokumen secara fleksibel sesuai kebutuhan. Atau, Anda dapat menggunakan modul format data XML Jackson Faster untuk Ion untuk memetakan dokumen Ion ke model objek Java (POJO) lama biasa.

Bagian berikut memberikan contoh kode pemrosesan data Ion menggunakan kedua teknik.

Mengimpor paket Ion

Tambahkan artefak ion-java sebagai dependensi dalam proyek Java Anda.

Gradle
dependencies { compile group: 'com.amazon.ion', name: 'ion-java', version: '1.6.1' }
Maven
<dependencies> <dependency> <groupId>com.amazon.ion</groupId> <artifactId>ion-java</artifactId> <version>1.6.1</version> </dependency> </dependencies>

Impor paket Ion berikut.

import com.amazon.ion.IonStruct; import com.amazon.ion.IonSystem; import com.amazon.ion.system.IonSystemBuilder;

Tambahkan artefak jackson-dataformat-ionsebagai dependensi dalam proyek Java Anda. QLDBmembutuhkan versi 2.10.0 atau yang lebih baru.

Gradle
dependencies { compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-ion', version: '2.10.0' }
Maven
<dependencies> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-ion</artifactId> <version>2.10.0</version> </dependency> </dependencies>

Impor paket Ion berikut.

import com.amazon.ion.IonReader; import com.amazon.ion.IonStruct; import com.amazon.ion.system.IonReaderBuilder; import com.amazon.ion.system.IonSystemBuilder; import com.fasterxml.jackson.dataformat.ion.IonObjectMapper; import com.fasterxml.jackson.dataformat.ion.ionvalue.IonValueMapper;

Inisialisasi Ion

IonSystem SYSTEM = IonSystemBuilder.standard().build();
IonObjectMapper MAPPER = new IonValueMapper(IonSystemBuilder.standard().build());

Membuat objek Ion

Contoh kode berikut membuat objek Ion dengan menggunakan IonStruct antarmuka dan metode bawaannya.

IonStruct ionStruct = SYSTEM.newEmptyStruct(); ionStruct.put("GovId").newString("TOYENC486FH"); ionStruct.put("FirstName").newString("Brent"); System.out.println(ionStruct.toPrettyString()); // prints a nicely formatted copy of ionStruct

Misalkan Anda memiliki kelas model JSON -mapped bernamaPerson, sebagai berikut.

import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public static class Person { private final String firstName; private final String govId; @JsonCreator public Person(@JsonProperty("FirstName") final String firstName, @JsonProperty("GovId") final String govId) { this.firstName = firstName; this.govId = govId; } @JsonProperty("FirstName") public String getFirstName() { return firstName; } @JsonProperty("GovId") public String getGovId() { return govId; } }

Contoh kode berikut menciptakan sebuah IonStruct objek dari sebuah instance dariPerson.

IonStruct ionStruct = (IonStruct) MAPPER.writeValueAsIonValue(new Person("Brent", "TOYENC486FH"));

Membaca objek Ion

Contoh kode berikut mencetak setiap bidang ionStruct instance.

// ionStruct is an instance of IonStruct System.out.println(ionStruct.get("GovId")); // prints TOYENC486FH System.out.println(ionStruct.get("FirstName")); // prints Brent

Contoh kode berikut membaca sebuah IonStruct objek dan memetakannya ke instancePerson.

// ionStruct is an instance of IonStruct IonReader reader = IonReaderBuilder.standard().build(ionStruct); Person person = MAPPER.readValue(reader, Person.class); System.out.println(person.getFirstName()); // prints Brent System.out.println(person.getGovId()); // prints TOYENC486FH

Untuk informasi selengkapnya tentang bekerja dengan Ion, lihat dokumentasi Amazon Ion di GitHub. Untuk contoh kode lebih lanjut tentang bekerja dengan Ion inQLDB, lihatBekerja dengan tipe data Amazon Ion di Amazon QLDB.