ترحيل التطبيق الخاص بك لاستخدام Azure Cosmos DB Java SDK الإصدار الرابع

ينطبق على: NoSQL

هام

برجاء عرض Azure Cosmos DB Java SDK v4 ملاحظات الإصدار ومستودع Maven وتلميحات أداءحزمة تطوير برامج Java Azure Cosmos DB - الإصدار 4 ودليل استكشاف الأخطاء وإصلاحها الخاص بـحزمة تطوير برامج Java Azure Cosmos DB - الإصدار 4 لمزيد من المعلومات.

هام

نظراً لأن Azure Cosmos DB Java SDK الإصدار 4 يحتوي على إنتاجية محسّنة تصل إلى 20٪، ووضع مباشر قائم على بروتوكول تحكم الإرسال ودعم لأحدث ميزات خدمة الواجهة الخلفية، نوصيك بالترقية إلى الإصدار 4 في الفرصة التالية. مواصلة القراءة أدناه لمعرفة المزيد.

قم بالتحديث إلى أحدث إصدار من Azure Cosmos DB Java SDK للحصول على أفضل ما يجب أن تقدمه Azure Cosmos DB - خدمة قاعدة بيانات غير علائقية مُدارة ذات أداء تنافسي، وتوافر خمسة، وإدارة موارد فريدة من نوعها، والمزيد. توضح هذه المقالة كيفية ترقية تطبيق Java الحالي الذي يستخدم Azure Cosmos DB Java SDK أقدم إلى Azure Cosmos DB Java SDK 4.0 الأحدث لواجهة برمجة التطبيقات ل NoSQL. يتوافق Azure Cosmos DB Java SDK الإصدار 4 مع الحزمة com.azure.cosmos. يمكنك استخدام الإرشادات الواردة في هذا المستند إذا كنت تقوم بترحيل تطبيقك من أي من حزم SDK التالية لـ Azure Cosmos DB Java:

  • مزامنة Java SDK 2.x.x
  • عدم مزامنة Java SDK 2.x.x
  • Java SDK 3.x.x

تطبيق Azure Cosmos DB Java SDK وتعيينات الحزم

يسرد الجدول التالي مجموعات تطوير Java SDK مختلفة لـ Azure Cosmos DB واسم الحزمة ومعلومات الإصدار:

Java SDK تاريخ الإصدار واجهات برمجة التطبيقات المجمعة Maven Jar اسم حزمة Java مرجع API ملاحظات الإصدار تاريخ الإيقاف
غير متزامن 2.x.x 2018 يونيو غير متزامن (RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx API ملاحظات الإصدار 31 أغسطس 2024
مزامنة 2.x.x سبتمبر 2018 مزامنة com.microsoft.azure::azure-documentdb com.microsoft.azure.cosmosdb API 29 فبراير 2024
3.x.x يوليو 2019 غير متزامن (مفاعل) / مزامنة com.microsoft.azure::azure-cosmos com.azure.data.cosmos API - 31 أغسطس 2024
4.0 يونيو 2020 غير متزامن (مفاعل) / مزامنة com.azure::azure-cosmos com.azure.cosmos API - -

تغييرات تنفيذ مستوى SDK

فيما يلي الاختلافات الرئيسية في التنفيذ بين حزم SDK المختلفة:

تم استبدال RxJava بالمفاعل في إصدارات Azure Cosmos DB Java SDK 3.x.x و4.0

إذا لم تكن معتاداً على البرمجة غير المتزامنة أو البرمجة التفاعلية، فراجع دليل نمط المفاعل للحصول على مقدمة حول البرمجة غير المتزامنة وProject Reactor. قد يكون هذا الدليل مفيداً إذا كنت تستخدم Azure Cosmos DB Sync Java SDK 2.x.x أو واجهة برمجة التطبيقات المتزامنة Azure Cosmos DB Java SDK 3.x.x في الماضي.

إذا كنت تستخدم Azure Cosmos DB لمزامنة Java SDK 2.xx، وكنت تخطط للترحيل إلى 4.0 SDK، فراجع Reactor مقابل RxJava Guide للحصول على إرشادات حول تحويل رمز RxJava لاستخدام Reactor.

يحتوي Azure Cosmos DB Java SDK الإصدار 4 على وضع اتصال مباشر في كل من واجهات برمجة التطبيقات الغير متزامنة والمتزامنة

إذا كنت تستخدم Azure Cosmos DB Sync Java SDK 2.x.x، فلاحظ أن وضع الاتصال المباشر المستند إلى بروتوكول تحكم الإرسال (على عكس بروتوكول نقل نص تشعبي) يتم تنفيذه في Azure Cosmos DB Java SDK 4.0 لكل من واجهة برمجة التطبيقات المتزامنة وغير المتزامنة.

تغييرات مستوى واجهة برمجة التطبيقات

فيما يلي التغييرات على مستوى واجهة برمجة التطبيقات في Azure Cosmos DB Java SDK 4.x.x مقارنة بمجموعات SDK السابقة (Java SDK 3.x.x وAsync Java SDK 2.x.x وSync Java SDK 2.x.x):

اصطلاحات تسمية Azure Cosmos DB Java SDK

  • يشير الإصداران 3.x.x و4.0 من Azure Cosmos DB Java SDK إلى موارد العميل كـ Cosmos<resourceName>. على سبيل المثال، CosmosClient، CosmosDatabase، CosmosContainer. بينما في الإصدار 2.x.x، لا تحتوي حزم تطوير برامج Java SDK من Azure Cosmos DB على نظام تسمية موحد.

  • توفر Azure Cosmos DB Java SDK 3.x.x و4.0 كلاً من واجهات برمجة التطبيقات المتزامنة وغير المتزامنة.

    • Java SDK 4.0: تنتمي جميع الفئات إلى واجهات برمجة التطبيقات المتزامنة ما لم يتم إلحاق اسم الفئة بـ Asyncبعد Cosmos.

    • Java SDK 3.x.x: تنتمي جميع الفئات إلى واجهات برمجة التطبيقات المتزامنة ما لم يتم إلحاق اسم الفئة بـ Asyncبعد Cosmos.

    • Async Java SDK 2.x.x: أسماء الفئات مشابهة لـ Sync Java SDK 2.x.x، إلا إن الاسم يبدأ بـ غير متزامن.

هيكل واجهات برمجة التطبيقات الهرمي

يقدم Azure Cosmos DB Java SDK 4.0 و3.x.x هيكل واجهات برمجة تطبيقات هرمية تنظم العملاء وقواعد البيانات والحاويات بطريقة متداخلة كما هو موضح في مقتطف التعليمات البرمجية 4.0 SDK التالي:

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

في الإصدار 2.x.x من Azure Cosmos DB Java SDK، يتم تنفيذ جميع العمليات على الموارد والمستندات من خلال مثيل العميل.

تقديم المستندات

في Azure Cosmos DB Java SDK 4.0، تعد أدوات POJO المخصصة وJsonNodesالخيارين لقراءة المستندات وكتابتها من Azure Cosmos DB.

في Azure Cosmos DB Java SDK 3.x.x، يتم عرض الكائن CosmosItemPropertiesبواسطة واجهة برمجة التطبيقات العامة ويتم تقديمه كتمثيل للمستند. لم يعد يتم عرض هذه الفئة علناً في الإصدار 4.0.

عمليات الاستيراد

  • تبدأ حزم Azure Cosmos DB Java SDK 4.0 بـ com.azure.cosmos

  • تبدأ حزم Azure Cosmos DB Java SDK 3.x.x بـ com.azure.data.cosmos

  • تبدأ حزم Azure Cosmos DB Java SDK 2.x.x Sync API بـ com.microsoft.azure.documentdb

  • يضع Azure Cosmos DB Java SDK 4.0 عدة فئات في حزمة متداخلة com.azure.cosmos.models. بعض هذه الحزم تشمل:

    • CosmosContainerResponse
    • CosmosDatabaseResponse
    • CosmosItemResponse
    • نظائر واجهات برمجة التطبيقات غير المتزامنة لجميع الحزم المذكورة أعلاه
    • CosmosContainerProperties
    • FeedOptions
    • PartitionKey
    • IndexingPolicy
    • IndexingMode....وما إلى ذلك.

المُوصلات

يعرض Azure Cosmos DB Java SDK 4.0 طرق getوset للوصول إلى أعضاء المثيل. على سبيل المثال، CosmosContainer المثيل container.getId() له container.setId() وأساليب.

هذا يختلف عن Azure Cosmos DB Java SDK 3.x.x الذي يعرض واجهة بطلاقة. على سبيل المثال، CosmosSyncContainerمثيل لهcontainer.id() والذي تم تحميله بشكل زائد للحصول على القيمة idأو تعيينها.

إدارة تعارضات التبعية

يمكن أن تؤدي الترقية من Azure Cosmos DB Java SDK V2 إلى V4 إلى تعارضات التبعية بسبب التغييرات في المكتبات المستخدمة من قبل SDK. يتطلب حل هذه التعارضات إدارة دقيقة للتبعيات.

  1. فهم التبعيات الجديدة: يحتوي Azure Cosmos DB V4 SDK على مجموعة خاصة به من التبعيات التي قد تكون مختلفة عن تلك الموجودة في الإصدارات السابقة. تأكد من أنك على دراية بهذه التبعيات:

    • 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. إزالة التبعيات المتعارضة: ابدأ بإزالة التبعيات المتعلقة بالإصدارات السابقة من SDK من ملفك pom.xml . تتضمن azure-cosmosdb هذه التبعيات وأي تبعيات متعالية قد يكون لدى SDK القديمة.

  3. إضافة تبعيات V4 SDK: أضف V4 SDK وتبعياتها إلى .pom.xml إليك مثال:

    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-cosmos</artifactId>
        <version>4.x.x</version> <!-- Use the latest version available -->
    </dependency>
    
  4. التحقق من تعارضات التبعية: استخدم الأمر Maven dependency:tree لإنشاء شجرة تبعية وتحديد أي تعارضات. تشغيل:

    mvn dependency:tree
    

    ابحث عن أي إصدارات متعارضة من التبعيات. غالبا ما تحدث هذه التعارضات مع مكتبات مثل reactor-coreو netty-handlerguavaو وjackson.

  5. استخدام إدارة التبعية: إذا واجهت تعارضات في الإصدار، فقد تحتاج إلى تجاوز الإصدارات المسببة للمشاكل باستخدام القسم في <dependencyManagement> .pom.xml فيما يلي مثال لفرض إصدار معين من 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. استبعاد التبعيات العابرة: في بعض الأحيان، قد تحتاج إلى استبعاد التبعيات العابرة التي جلبتها التبعيات الأخرى. على سبيل المثال، إذا كانت مكتبة أخرى تتضمن إصدارا قديما من تبعية تتعارض، يمكنك استبعادها كما يلي:

    <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. إعادة البناء والاختبار: بعد إجراء هذه التغييرات، أعد إنشاء مشروعك واختبره بدقة للتأكد من أن التبعيات الجديدة تعمل بشكل صحيح وأنه لا تحدث تعارضات في وقت التشغيل.

مقارنات قصاصة برمجية

إنشاء الموارد

يُظهر مقتطف الشفرة التالي الاختلافات في كيفية إنشاء الموارد بين واجهات برمجة التطبيقات 4.0, 3.x.x غير المتزامنة، و2.x.x المتزامنة، و2.x.x غير المتزامنة:


// 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();

عمليات العنصر

يوضح مقتطف التعليمات البرمجية التالي الاختلافات في كيفية تنفيذ عمليات العنصر بين واجهات برمجة تطبيقات 4.0، 3.x.x غير المتزامنة، و2.x.x المتزامنة، و2.x.x غير المتزامنة:


// 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.

الفهرسة

يوضح مقتطف التعليمات البرمجية التالي الاختلافات في كيفية إنشاء الفهرسة بين واجهات برمجة تطبيقات 4.0، 3.x.x غير المتزامنة، و2.x.x المتزامنة، و2.x.x غير المتزامنة:


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);

الإجراءات المخزنة

يوضح مقتطف التعليمات البرمجية التالي الاختلافات في كيفية إنشاء الإجراءات المخزنة بين واجهات برمجة تطبيقات 4.0، 3.x.x غير المتزامنة، و2.x.x المتزامنة، و2.x.x غير المتزامنة:


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();

موجز التغيير

يوضح مقتطف الشفرة التالي الاختلافات في كيفية تنفيذ عمليات الخلاصة بين واجهات برمجة التطبيقات غير المتزامنة 4.0 و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.elastic())
        .subscribe();

مدة البقاء على مستوى الحاوية (TTL)

يوضح مقتطف الشفرة التالي الاختلافات في كيفية إنشاء وقت بقاء للبيانات في الحاوية بين واجهات برمجة تطبيقات 4.0، 3.x.x غير المتزامنة، و2.x.x المتزامنة، و2.x.x غير المتزامنة:


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");

مدة البقاء على مستوى العنصر (TTL)

يوضح مقتطف التعليمات البرمجية التالي الاختلافات في كيفية إنشاء وقت للعيش لعنصر ما بين واجهات برمجة تطبيقات 4.0, 3.x.x غير المتزامنة، و2.x.x المتزامنة، و2.x.x غير المتزامنة:


// 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
);

الخطوات التالية