Migrasikan aplikasi Anda untuk menggunakan Azure Cosmos DB Java SDK v4

BERLAKU UNTUK: NoSQL

Penting

Untuk informasi selengkapnya, lihat Catatan rilis Azure Cosmos DB Java SDK v4, repositori Maven, tips performa Azure Cosmos DB Java SDK v4, dan panduan pemecahan masalah Azure Cosmos DB Java SDK v4.

Penting

Karena Azure Cosmos DB Java SDK v4 memiliki throughput yang ditingkatkan hingga 20%, mode langsung berbasis TCP, dan dukungan untuk fitur layanan backend terbaru, sebaiknya tingkatkan ke v4 pada kesempatan berikutnya. Lanjutkan membaca di bawah ini untuk mempelajari selengkapnya.

Perbarui ke Azure Cosmos DB Java SDK terbaru untuk mendapatkan tawaran terbaik dari Azure Cosmos DB - layanan database non-hubungan yang dikelola dengan performa kompetitif, ketersediaan jam kerja lima-sembilan, tata kelola sumber daya unik, dan banyak lagi. Artikel ini menjelaskan cara meningkatkan aplikasi Java Anda yang sudah ada yang menggunakan Azure Cosmos DB Java SDK yang lebih lama ke Azure Cosmos DB Java SDK 4.0 yang lebih baru untuk API untuk NoSQL. Azure Cosmos DB Java SDK v4 sesuai dengan paket com.azure.cosmos. Anda dapat menggunakan instruksi dalam dokumen ini jika Anda memigrasikan aplikasi Anda dari salah satu SDK Azure Cosmos DB Java berikut:

  • Sync Java SDK 2.x.x
  • Async Java SDK 2.x.x
  • Java SDK 3.x.x

Azure Cosmos DB Java SDK dan pemetaan paket

Tabel berikut ini mencantumkan Azure Cosmos DB Java SDK yang berbeda, nama paket, dan informasi rilis:

Java SDK Tanggal Rilis API yang Dibundel Maven Jar Nama paket Java Referensi API Catatan Rilis Tanggal pensiun
Async 2.x.x Juni 2018 Async(RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx API Catatan Rilis Sabtu, 31 Agustus 2024
Sync 2.x.x Sept 2018 Sinkronisasi com.microsoft.azure::azure-documentdb com.microsoft.azure.cosmosdb API Kamis, 29 Februari 2024
3.x.x Juli 2019 Async(Reactor)/Sync com.microsoft.azure::azure-cosmos com.azure.data.cosmos API - Sabtu, 31 Agustus 2024
4,0 2020 Juni Async(Reactor)/Sync com.azure::azure-cosmos com.azure.cosmos API - -

Perubahan implementasi tingkat SDK

Berikut ini adalah perbedaan implementasi utama antara SDK yang berbeda:

RxJava diganti dengan reaktor di Azure Cosmos DB Java SDK versi 3.x.x dan 4.0

Jika Anda tidak terbiasa dengan pemrograman asinkron atau Pemrograman Reaktif, lihat panduan pola Reaktor untuk pengenalan pemrograman asinkron dan Reaktor Proyek. Panduan ini mungkin berguna jika Anda telah menggunakan Azure Cosmos DB Sync Java SDK 2.x.x atau Azure Cosmos DB Java SDK 3.x.x Sync API di masa lalu.

Jika Anda telah menggunakan Azure Cosmos DB Async Java SDK 2.x.x, dan Anda berencana untuk bermigrasi ke SDK 4.0, lihat Panduan Reaktor vs RxJava untuk panduan tentang mengonversi kode RxJava untuk menggunakan Reaktor.

Azure Cosmos DB Java SDK v4 memiliki mode konektivitas langsung di API Async dan Sync

Jika Anda telah menggunakan Azure Cosmos DB Sync Java SDK 2.x.x, perhatikan bahwa mode koneksi langsung berdasarkan TCP (dibandingkan dengan HTTP) diterapkan di Azure Cosmos DB Java SDK 4.0 untuk API Async dan Sync.

Perubahan level API

Berikut ini adalah perubahan level API di Azure Cosmos DB Java SDK 4.x.x dibandingkan dengan SDK sebelumnya (Java SDK 3.x.x, Async Java SDK 2.x.x, dan Sync Java SDK 2.x.x):

Azure Cosmos DB Java SDK naming conventions

  • Azure Cosmos DB Java SDK 3.x.x dan 4.0 menyebut sumber daya klien sebagai Cosmos<resourceName>. Misalnya, CosmosClient, CosmosDatabase, CosmosContainer. Sedangkan dalam versi 2.x.x, Azure Cosmos DB Java SDK tidak memiliki skema penamaan yang seragam.

  • Azure Cosmos DB Java SDK 3.x.x and 4.0 menawarkan API Sync dan Async.

    • Java SDK 4.0 : Semua kelas milik Sync API kecuali nama kelas ditambahkan Async setelah Cosmos.

    • Java SDK 3.x.x: Semua kelas milik Async API kecuali nama kelas ditambahkan Async setelah Cosmos.

    • Async Java SDK 2.x.x: Nama kelas mirip dengan Sync Java SDK 2.x.x, namun namanya dimulai dengan Async.

Struktur API Hierarki

Azure Cosmos DB Java SDK 4.0 dan 3.x.x memperkenalkan struktur API hierarkis yang mengatur klien, database, dan kontainer dalam mode bersarang seperti yang ditunjukkan dalam cuplikan kode SDK 4.0 berikut:

CosmosContainer container = client.getDatabase("MyDatabaseName").getContainer("MyContainerName");

Dalam versi 2.x.x dari Azure Cosmos DB Java SDK, semua operasi pada sumber daya dan dokumen dilakukan melalui instans klien.

Mewakili dokumen

Di Azure Cosmos DB Java SDK 4.0, POJO kustom dan JsonNodes merupakan dua opsi untuk membaca dan menulis dokumen dari Azure Cosmos DB.

Dalam Azure Cosmos DB Java SDK 3.x.x, objek CosmosItemProperties diekspos oleh API publik dan berfungsi sebagai representasi dokumen. Kelas ini tidak lagi diekspos secara publik di versi 4.0.

Impor

  • Paket Azure Cosmos DB Java SDK 4.0 dimulai dengan com.azure.cosmos

  • Paket Azure Cosmos DB Java SDK 3.x.x dimulai dengan com.azure.data.cosmos

  • Sync API paket Azure Cosmos DB Java SDK 2.x.x dimulai dengan com.microsoft.azure.documentdb

  • Azure Cosmos DB Java SDK 4.0 menempatkan beberapa kelas dalam paket com.azure.cosmos.models bersarang. Beberapa paket ini meliputi:

    • CosmosContainerResponse
    • CosmosDatabaseResponse
    • CosmosItemResponse
    • Analog Async API untuk semua paket di atas
    • CosmosContainerProperties
    • FeedOptions
    • PartitionKey
    • IndexingPolicy
    • IndexingMode ...dll.

Pengakses

Azure Cosmos DB Java SDK 4.0 mengekspos metode get dan set untuk mengakses anggota instans. Misalnya, CosmosContainer instans memiliki metode container.getId() dan container.setId().

Ini berbeda dengan Azure Cosmos DB Java SDK 3.x.x yang memaparkan antarmuka yang fasih. Misalnya, instans CosmosSyncContainer memiliki container.id() kelebihan beban untuk mendapatkan atau menetapkan nilai id.

Perbandingan cuplikan kode

Membuat sumber daya

Cuplikan kode berikut menunjukkan perbedaan bagaimana sumber daya dibuat antara 4.0, 3.x.x Async, 2.x.x Sync, and 2.x.x Async API:


// Create Async client.
// Building an async client is still a sync operation.
CosmosAsyncClient client = new CosmosClientBuilder()
        .endpoint("your.hostname")
        .key("yourmasterkey")
        .consistencyLevel(ConsistencyLevel.EVENTUAL)
        .buildAsyncClient();

// Create database with specified name
client.createDatabaseIfNotExists("YourDatabaseName")
        .flatMap(databaseResponse -> {
            testDatabaseAsync = client.getDatabase("YourDatabaseName");
            // Container properties - name and partition key
            CosmosContainerProperties containerProperties =
                    new CosmosContainerProperties("YourContainerName", "/id");

            // Provision manual throughput
            ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);

            // Create container
            return database.createContainerIfNotExists(containerProperties, throughputProperties);
        }).flatMap(containerResponse -> {
    testContainerAsync = database.getContainer("YourContainerName");
    return Mono.empty();
}).subscribe();

Operasi item

Cuplikan kode berikut menunjukkan perbedaan bagaimana operasi item dilakukan antara 4.0, 3.x.x Async, 2.x.x Sync, and 2.x.x Async API:


// Container is created. Generate many docs to insert.
int number_of_docs = 50000;
ArrayList<JsonNode> docs = generateManyDocs(number_of_docs);

// Insert many docs into container...
Flux.fromIterable(docs)
        .flatMap(doc -> testContainerAsync.createItem(doc))
        .subscribe(); // ...Subscribing triggers stream execution.

Pengindeksan

Cuplikan kode berikut menunjukkan perbedaan bagaimana pengindeksan dibuat antara 4.0, 3.x.x Async, 2.x.x Sync, and 2.x.x Async API:


CosmosContainerProperties containerProperties = new CosmosContainerProperties(containerName, "/lastName");

// Custom indexing policy
IndexingPolicy indexingPolicy = new IndexingPolicy();
indexingPolicy.setIndexingMode(IndexingMode.CONSISTENT);

// Included paths
List<IncludedPath> includedPaths = new ArrayList<>();
includedPaths.add(new IncludedPath("/*"));
indexingPolicy.setIncludedPaths(includedPaths);

// Excluded paths
List<ExcludedPath> excludedPaths = new ArrayList<>();
excludedPaths.add(new ExcludedPath("/name/*"));
indexingPolicy.setExcludedPaths(excludedPaths);

containerProperties.setIndexingPolicy(indexingPolicy);

ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);

database.createContainerIfNotExists(containerProperties, throughputProperties);
CosmosAsyncContainer containerIfNotExists = database.getContainer(containerName);

Prosedur tersimpan

Cuplikan kode berikut menunjukkan perbedaan bagaimana prosedur tersimpan dibuat antara 4.0, 3.x.x Async, 2.x.x Sync, and 2.x.x Async API:


logger.info("Creating stored procedure...\n");

String sprocId = "createMyDocument";

String sprocBody = "function createMyDocument() {\n" +
        "var documentToCreate = {\"id\":\"test_doc\"}\n" +
        "var context = getContext();\n" +
        "var collection = context.getCollection();\n" +
        "var accepted = collection.createDocument(collection.getSelfLink(), documentToCreate,\n" +
        "    function (err, documentCreated) {\n" +
        "if (err) throw new Error('Error' + err.message);\n" +
        "context.getResponse().setBody(documentCreated.id)\n" +
        "});\n" +
        "if (!accepted) return;\n" +
        "}";

CosmosStoredProcedureProperties storedProcedureDef = new CosmosStoredProcedureProperties(sprocId, sprocBody);
container.getScripts()
        .createStoredProcedure(storedProcedureDef,
                new CosmosStoredProcedureRequestOptions()).block();

// ...

logger.info(String.format("Executing stored procedure %s...\n\n", sprocId));

CosmosStoredProcedureRequestOptions options = new CosmosStoredProcedureRequestOptions();
options.setPartitionKey(new PartitionKey("test_doc"));

container.getScripts()
        .getStoredProcedure(sprocId)
        .execute(null, options)
        .flatMap(executeResponse -> {
            logger.info(String.format("Stored procedure %s returned %s (HTTP %d), at cost %.3f RU.\n",
                    sprocId,
                    executeResponse.getResponseAsString(),
                    executeResponse.getStatusCode(),
                    executeResponse.getRequestCharge()));
            return Mono.empty();
        }).block();

Umpan perubahan

Cuplikan kode berikut menunjukkan perbedaan bagaimana operasi umpan perubahan dijalankan antara 4.0 dan 3.x.x Async API:


ChangeFeedProcessor changeFeedProcessorInstance =
        new ChangeFeedProcessorBuilder()
                .hostName(hostName)
                .feedContainer(feedContainer)
                .leaseContainer(leaseContainer)
                .handleChanges((List<JsonNode> docs) -> {
                    logger.info("--->setHandleChanges() START");

                    for (JsonNode document : docs) {
                        try {
                            //Change Feed hands the document to you in the form of a JsonNode
                            //As a developer you have two options for handling the JsonNode document provided to you by Change Feed
                            //One option is to operate on the document in the form of a JsonNode, as shown below. This is great
                            //especially if you do not have a single uniform data model for all documents.
                            logger.info("---->DOCUMENT RECEIVED: " + OBJECT_MAPPER.writerWithDefaultPrettyPrinter()
                                    .writeValueAsString(document));

                            //You can also transform the JsonNode to a POJO having the same structure as the JsonNode,
                            //as shown below. Then you can operate on the POJO.
                            CustomPOJO pojo_doc = OBJECT_MAPPER.treeToValue(document, CustomPOJO.class);
                            logger.info("----=>id: " + pojo_doc.getId());

                        } catch (JsonProcessingException e) {
                            e.printStackTrace();
                        }
                    }
                    logger.info("--->handleChanges() END");

                })
                .buildChangeFeedProcessor();

// ...

changeFeedProcessorInstance.start()
        .subscribeOn(Schedulers.elastic())
        .subscribe();

Tingkat kontainer Time-To-Live(TTL)

Cuplikan kode berikut menunjukkan perbedaan cara membuat waktu aktif untuk data dalam kontainer antara 4.0, 3.x.x Async, 2.x.x Sync, and 2.x.x Async API:


CosmosAsyncContainer container;

// Create a new container with TTL enabled with default expiration value
CosmosContainerProperties containerProperties = new CosmosContainerProperties("myContainer", "/myPartitionKey");
containerProperties.setDefaultTimeToLiveInSeconds(90 * 60 * 60 * 24);
ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);
database.createContainerIfNotExists(containerProperties, throughputProperties).block();
container = database.getContainer("myContainer");

Tingkat item Time-To-Live(TTL)

Cuplikan kode berikut menunjukkan perbedaan cara membuat waktu aktif untuk item antara 4.0, 3.x.x Async, 2.x.x Sync, and 2.x.x Async API:


// Include a property that serializes to "ttl" in JSON
class SalesOrder
{
    private String id;
    private String customerId;
    private Integer ttl;

    public SalesOrder(String id, String customerId, Integer ttl) {
        this.id = id;
        this.customerId = customerId;
        this.ttl = ttl;
    }

    public String getId() {return this.id;}
    public void setId(String new_id) {this.id = new_id;}
    public String getCustomerId() {return this.customerId;}
    public void setCustomerId(String new_cid) {this.customerId = new_cid;}
    public Integer getTtl() {return this.ttl;}
    public void setTtl(Integer new_ttl) {this.ttl = new_ttl;}

    //...
}


// Set the value to the expiration in seconds
SalesOrder salesOrder = new SalesOrder(
        "SO05",
        "CO18009186470",
        60 * 60 * 24 * 30  // Expire sales orders in 30 days
);

Langkah berikutnya