迁移应用程序以使用 Azure Cosmos DB Java SDK v4Migrate your application to use the Azure Cosmos DB Java SDK v4

重要

有关此 SDK 的详细信息,请查看 Azure Cosmos DB Java SDK v4 发行说明Maven 存储库、Azure Cosmos DB Java SDK v4 性能提示和 Azure Cosmos DB Java SDK v4 故障排除指南For more information about this SDK, please view the Azure Cosmos DB Java SDK v4 Release notes, Maven repository, Azure Cosmos DB Java SDK v4 performance tips, and Azure Cosmos DB Java SDK v4 troubleshooting guide.

本文介绍如何将使用较旧 Azure Cosmos DB Java SDK 的现有 Java 应用程序升级为使用较新的适用于 Core (SQL) API 的 Azure Cosmos DB Java SDK 4.0。This article explains how to upgrade your existing Java application that is using an older Azure Cosmos DB Java SDK to the newer Azure Cosmos DB Java SDK 4.0 for Core (SQL) API. Azure Cosmos DB Java SDK v4 对应于 com.azure.cosmos 包。Azure Cosmos DB Java SDK v4 corresponds to the com.azure.cosmos package. 如果要从以下任何 Azure Cosmos DB Java SDK 迁移应用程序,则可以使用此文档中的说明:You can use the instructions in this doc if you are migrating your application from any of the following Azure Cosmos DB Java SDKs:

  • Sync Java SDK 2.x.xSync Java SDK 2.x.x
  • Async Java SDK 2.x.xAsync Java SDK 2.x.x
  • Java SDK 3.x.xJava SDK 3.x.x

Azure Cosmos DB Java SDK 和包映射Azure Cosmos DB Java SDK's and package mappings

下表列出了不同的 Azure Cosmos DB Java SDK、包名称和发布信息:The following table lists different Azure Cosmos DB Java SDKs, the package name and the release information:

Java SDKJava SDK 发布日期Release Date 捆绑 APIBundled APIs Maven JarMaven Jar Java 包名称Java package name API 参考API Reference 发行说明Release Notes
Async 2.x.xAsync 2.x.x 2018 年 6 月June 2018 Async(RxJava)Async(RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx APIAPI 发行说明Release Notes
Sync 2.x.xSync 2.x.x 2018 年 9 月Sept 2018 同步Sync com.microsoft.azure::azure-documentdb com.microsoft.azure.cosmosdb APIAPI 发行说明Release Notes
3.x.x3.x.x 2019 年 7 月July 2019 Async(Reactor)/SyncAsync(Reactor)/Sync com.microsoft.azure::azure-cosmos com.azure.data.cosmos APIAPI -
4.04.0 2020 年 6 月June 2020 Async(Reactor)/SyncAsync(Reactor)/Sync com.azure::azure-cosmos com.azure.cosmos - APIAPI

SDK 级别实现更改SDK level implementation changes

以下是不同 SDK 之间的主要实现差异:The following are the key implementation differences between different SDKs:

在 Azure Cosmos DB Java SDK 3.x.x 和 4.0 版本中,RxJava 已替换为 ReactorRxJava is replaced with reactor in Azure Cosmos DB Java SDK versions 3.x.x and 4.0

如果你不熟悉异步编程或响应式编程,请参阅 Reactor 模式指南,了解异步编程和 Project Reactor。If you are unfamiliar with asynchronous programming or Reactive Programming, see the Reactor pattern guide for an introduction to async programming and Project Reactor. 如果你过去一直在使用 Azure Cosmos DB Sync Java SDK 2.x.x 或 Azure Cosmos DB Java SDK 3.x.x Sync API,本指南可能很有用。This guide may be useful if you have been using Azure Cosmos DB Sync Java SDK 2.x.x or Azure Cosmos DB Java SDK 3.x.x Sync API in the past.

如果你一直在使用 Azure Cosmos DB Async Java SDK 2.x.x,并计划迁移到 4.0 SDK,请参阅 Reactor 与 RxJava 指南,获取有关将 RxJava 代码转换为使用 Reactor 的指导。If you have been using Azure Cosmos DB Async Java SDK 2.x.x, and you plan on migrating to the 4.0 SDK, see the Reactor vs RxJava Guide for guidance on converting RxJava code to use Reactor.

Azure Cosmos DB Java SDK v4 在异步和同步 API 中具有直接连接模式Azure Cosmos DB Java SDK v4 has direct connectivity mode in both Async and Sync APIs

如果你一直在使用 Azure Cosmos DB Sync Java SDK 2.x.x,请注意,基于 TCP(而不是 HTTP)的直接连接模式已在适用于异步和同步 API 的 Azure Cosmos DB Java SDK 4.0 中实现。If you have been using Azure Cosmos DB Sync Java SDK 2.x.x, note that the direct connection mode based on TCP (as opposed to HTTP) is implemented in Azure Cosmos DB Java SDK 4.0 for both the Async and Sync APIs.

API 级别更改API level changes

以下是 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)相比的 API 级别更改:The following are the API level changes in Azure Cosmos DB Java SDK 4.x.x compared to previous SDKs (Java SDK 3.x.x, Async Java SDK 2.x.x, and Sync Java SDK 2.x.x):

Azure Cosmos DB Java SDK 命名约定

  • Azure Cosmos DB Java SDK 3.x.x 和 4.0 将客户端资源作为 Cosmos<resourceName> 引用。The Azure Cosmos DB Java SDK 3.x.x and 4.0 refer the client resources as Cosmos<resourceName>. 例如:CosmosClientCosmosDatabaseCosmosContainerFor example, CosmosClient, CosmosDatabase, CosmosContainer. 而在版本 2.x.x 中,Azure Cosmos DB Java SDK 没有统一的命名方案。Whereas in version 2.x.x, the Azure Cosmos DB Java SDKs don't have a uniform naming scheme.

  • Azure Cosmos DB Java SDK 3.x.x 和 4.0 同时提供同步和异步 API。Azure Cosmos DB Java SDK 3.x.x and 4.0 offer both Sync and Async APIs.

    • Java SDK 4.0:除非类名称在 Cosmos 后附加 Async,否则所有类都属于同步 API。Java SDK 4.0 : All the classes belong to the Sync API unless the class name is appended with Async after Cosmos.

    • Java SDK 3.x.x:除非类名称在 Cosmos 后附加Async,否则所有类都属于异步 API。Java SDK 3.x.x: All the classes belong to the Async API unless the class name is appended with Async after Cosmos.

    • Async Java SDK 2.x.x:类名称类似于 Sync Java SDK 2.x.x,但名称以 Async 开头。Async Java SDK 2.x.x: The class names are similar to Sync Java SDK 2.x.x, however the name starts with Async.

分层 API 结构Hierarchical API structure

Azure Cosmos DB Java SDK 4.0 和 3.x.x 引入了分层 API 结构,该结构以嵌套方式组织客户端、数据库和容器,如以下 4.0 SDK 代码片段所示:Azure Cosmos DB Java SDK 4.0 and 3.x.x introduce a hierarchical API structure that organizes the clients, databases, and containers in a nested fashion as shown in the following 4.0 SDK code snippet:

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

在 Azure Cosmos DB Java SDK 版本 2.x.x 中,对资源和文档执行的所有操作都通过客户端实例执行。In version 2.x.x of the Azure Cosmos DB Java SDK, all operations on resources and documents are performed through the client instance.

表示文档Representing documents

在 Azure Cosmos DB Java SDK 4.0 中,自定义 POJO 和 JsonNodes 是从 Azure Cosmos DB 读取和写入文档的两个选项。In Azure Cosmos DB Java SDK 4.0, custom POJO's and JsonNodes are the two options to read and write the documents from Azure Cosmos DB.

在 Azure Cosmos DB Java SDK 3.x.x 中,公共 API 公开 CosmosItemProperties 对象并用作文档表示形式。In the Azure Cosmos DB Java SDK 3.x.x, the CosmosItemProperties object is exposed by the public API and served as a document representation. 在版本 4.0 中,不再公开此类。This class is no longer exposed publicly in version 4.0.

导入Imports

  • Azure Cosmos DB Java SDK 4.0 包以 com.azure.cosmos 开头The Azure Cosmos DB Java SDK 4.0 packages begin with com.azure.cosmos

    • Azure Cosmos DB Java SDK 3.x.x 包以 com.azure.data.cosmos 开头Azure Cosmos DB Java SDK 3.x.x packages begin with com.azure.data.cosmos
  • Azure Cosmos DB Java SDK 4.0 将几个类放在嵌套包 com.azure.cosmos.models 中。Azure Cosmos DB Java SDK 4.0 places several classes in a nested package com.azure.cosmos.models. 其中一些包包括:Some of these packages include:

    • CosmosContainerResponse
    • CosmosDatabaseResponse
    • CosmosItemResponse
    • 所有上述包的异步 API 模拟The Async API analogs for all of the above packages
    • CosmosContainerProperties
    • FeedOptions
    • PartitionKey
    • IndexingPolicy
    • IndexingModeIndexingMode ...etc.

访问器Accessors

Azure Cosmos DB Java SDK 4.0 公开了访问实例成员 getset 方法。Azure Cosmos DB Java SDK 4.0 exposes get and set methods to access the instance members. 例如,CosmosContainer 实例具有 container.getId()container.setId() 方法。For example, the CosmosContainer instance has container.getId() and container.setId() methods.

这与 Azure Cosmos DB Java SDK 3.x.x 不同,后者公开了 Fluent 界面。This is different from Azure Cosmos DB Java SDK 3.x.x which exposes a fluent interface. 例如,CosmosSyncContainer 实例具有 container.id(),重载它可获取或设置 id 值。For example, a CosmosSyncContainer instance has container.id() which is overloaded to get or set the id value.

代码片段比较Code snippet comparisons

创建资源Create resources

以下代码片段显示了 4.0 和 3.x.x 异步 API 在资源创建方式上的差异:The following code snippet shows the differences in how resources are created between the 4.0 and 3.x.x Async APIs:


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

项操作Item operations

以下代码片段显示了 4.0 和 3.x.x 异步 API 在项操作执行方式上的差异:The following code snippet shows the differences in how item operations are performed between the 4.0 and 3.x.x Async APIs:


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

索引Indexing

以下代码片段显示了 4.0 和 3.x.x 异步 API 在索引创建方式上的差异:The following code snippet shows the differences in how indexing is created between the 4.0 and 3.x.x Async APIs:


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

存储过程Stored procedures

以下代码片段显示了 4.0 和 3.x.x 异步 API 在存储过程创建方式上的差异:The following code snippet shows the differences in how stored procedures are created between the 4.0 and 3.x.x Async APIs:


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

更改源Change feed

以下代码片段显示了 4.0 和 3.x.x 异步 API 在更改源操作执行方式上的差异:The following code snippet shows the differences in how change feed operations are executed between the 4.0 and 3.x.x Async APIs:


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)Container level Time-To-Live(TTL)

以下代码片段显示了 4.0 和 3.x.x 异步 API 在容器数据生存时间创建方式上的差异:The following code snippet shows the differences in how to create time to live for data in the container using the 4.0 and 3.x.x Async APIs:


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)Item level Time-To-Live(TTL)

以下代码片段显示了 4.0 和 3.x.x 异步 API 在项生存时间创建方式上的差异:The following code snippet shows the differences in how to create time to live for an item using the 4.0 and 3.x.x Async APIs:


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

后续步骤Next steps