Bagikan melalui


Memigrasikan aplikasi Anda untuk menggunakan Azure Cosmos DB Java SDK v4

Penting

Untuk informasi selengkapnya tentang SDK ini, silakan 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, kami sarankan Anda meningkatkan ke v4 pada kesempatan berikutnya. Lanjutkan membaca di bawah ini untuk mempelajari lebih lanjut.

Perbarui ke Azure Cosmos DB Java SDK terbaru untuk mendapatkan yang terbaik dari apa yang ditawarkan Azure Cosmos DB - layanan database nonrelasional terkelola dengan performa kompetitif, 99.999% ketersediaan, tata kelola sumber daya tak tertandingi, 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 com.azure.cosmos paket. Anda dapat menggunakan instruksi dalam dokumen ini jika Anda memigrasikan aplikasi Anda dari salah satu SDK Java Azure Cosmos DB berikut:

  • Sinkronkan 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 SDK Java Azure Cosmos DB 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 Asinkron(RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx API Catatan Rilis Sabtu, 31 Agustus 2024
Sinkronkan 2.x.x September 2018 Sinkronisasi com.microsoft.azure::azure-documentdb com.microsoft.azure.cosmosdb API 29 Februari 2024
3.x.x Juli 2019 Asinkron(Reaktor)/Sinkronisasi com.microsoft.azure::azure-cosmos com.azure.data.cosmos API - Sabtu, 31 Agustus 2024
4,0 2020 Juni Asinkron(Reaktor)/Sinkronisasi 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 Reactor.

Azure Cosmos DB Java SDK v4 memiliki mode konektivitas langsung di API Asinkron dan Sinkronisasi

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

Perubahan tingkat API

Berikut ini adalah perubahan tingkat 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):

Konvensi penamaan Azure Cosmos DB Java SDK

  • 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 dan 4.0 menawarkan API Sync dan Async.

    • Java SDK 4.0 : Semua kelas milik Api Sinkronisasi kecuali nama kelas ditambahkan dengan Async setelah Cosmos.

    • Java SDK 3.x.x: Semua kelas milik API Asinkron kecuali nama kelas ditambahkan dengan 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 hierarkis

Azure Cosmos DB Java SDK 4.0 dan 3.x.x memperkenalkan struktur API hierarkis yang mengatur klien, database, dan kontainer dengan cara berlapis 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.

Di Azure Cosmos DB Java SDK 3.x.x, CosmosItemProperties objek diekspos oleh API publik dan dilayani 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

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

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

    • CosmosContainerResponse
    • CosmosDatabaseResponse
    • CosmosItemResponse
    • Padanan Async API untuk semua paket di atas
    • CosmosContainerProperties
    • FeedOptions
    • PartitionKey
    • IndexingPolicy
    • `IndexingMode ... dsb.`

Accessors

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

Ini berbeda dari Azure Cosmos DB Java SDK 3.x.x yang mengekspos antarmuka yang fasih. Misalnya, sebuah instance CosmosSyncContainer memiliki container.id() yang di-overload untuk mendapatkan atau mengatur nilai id.

Mengelola Konflik Dependensi

Peningkatan dari Azure Cosmos DB Java SDK V2 ke V4 dapat menimbulkan konflik dependensi karena perubahan pustaka yang digunakan oleh SDK. Mengatasi konflik ini memerlukan manajemen dependensi yang cermat.

  1. Pahami Dependensi Baru: Azure Cosmos DB V4 SDK memiliki serangkaian dependensinya sendiri yang mungkin berbeda dari yang ada di versi sebelumnya. Pastikan Anda mengetahui dependensi ini:

    • azure-cosmos
    • reactor-core
    • reactor-netty
    • netty-handler
    • guava
    • slf4j-api
    • jackson-databind
    • jackson-annotations
    • jackson-core
    • commons-lang3
    • commons-collections4
    • azure-core
    • azure-core-http-netty
  2. Hapus Dependensi yang Berkonflik: Mulailah dengan menghapus dependensi yang terkait dengan versi SDK sebelumnya dari file Anda pom.xml . Ini termasuk azure-cosmosdb dan dependensi transitif apa pun yang mungkin dimiliki SDK lama.

  3. Tambahkan Dependensi V4 SDK: Tambahkan V4 SDK dan dependensinya ke pom.xml. Berikut adalah sebuah contoh:

    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-cosmos</artifactId>
        <version>4.x.x</version> <!-- Use the latest version available -->
    </dependency>
    
  4. Periksa Konflik Dependensi: Gunakan perintah Maven dependency:tree untuk menghasilkan pohon dependensi dan mengidentifikasi konflik apa pun. Jalankan:

    mvn dependency:tree
    

    Cari versi ketergantungan yang bertabrakan atau tidak sesuai. Konflik ini sering terjadi dengan pustaka seperti reactor-core, netty-handler, guava, dan jackson.

  5. Gunakan Manajemen Dependensi: Jika Anda mengalami konflik versi, Anda mungkin perlu mengabaikan versi bermasalah menggunakan bagian <dependencyManagement> di dalam pom.xml Anda. Berikut adalah contoh untuk memberlakukan versi tertentu dari reactor-core:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.projectreactor</groupId>
                <artifactId>reactor-core</artifactId>
                <version>3.x.x</version> <!-- Use a compatible version -->
            </dependency>
            <!-- Repeat for any other conflicting dependencies -->
        </dependencies>
    </dependencyManagement>
    
  6. Mengecualikan Dependensi Transitif: Terkadang, Anda mungkin perlu mengecualikan dependensi transitif yang dibawa oleh dependensi lain. Misalnya, jika pustaka lain membawa versi dependensi lama yang berkonflik, Anda dapat mengecualikannya seperti ini:

    <dependency>
        <groupId>some.group</groupId>
        <artifactId>some-artifact</artifactId>
        <version>x.x.x</version>
        <exclusions>
            <exclusion>
                <groupId>conflicting.group</groupId>
                <artifactId>conflicting-artifact</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
  7. Bangun ulang dan Uji: Setelah membuat perubahan ini, bangun kembali proyek Anda dan uji secara menyeluruh untuk memastikan bahwa dependensi baru berfungsi dengan benar dan tidak ada konflik runtime yang terjadi.

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, dan 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, dan 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 cara pengindeksan dibuat antara 4.0, 3.x.x Async, 2.x.x Sync, dan 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 yang disimpan

Cuplikan kode berikut menunjukkan perbedaan cara prosedur tersimpan dibuat antara 4.0, 3.x.x Async, 2.x.x Sync, dan 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 data

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


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.boundedElastic())
        .subscribe();

Tingkat kontainer Time-to-Live(TTL)

Cuplikan kode berikut menunjukkan perbedaan dalam cara membuat masa berlaku untuk data dalam wadah antara API 4.0, 3.x.x Asinkron, 2.x.x Sinkron, dan 2.x.x Asinkron:


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 hidup untuk item antara 4.0, 3.x.x Async, 2.x.x Sync, dan 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 selanjutnya