Partilhar via


Migre seu aplicativo para usar o SDK Java do Azure Cosmos DB v4

APLICA-SE A: NoSQL

Importante

Para obter mais informações sobre este SDK, consulte as notas de versão do SDK Java do Azure Cosmos DB v4, o repositório Maven, as dicas de desempenho do SDK Java do Azure Cosmos DB v4 e o guia de solução de problemas do SDK Java do Azure Cosmos DB v4.

Importante

Como o SDK Java v4 do Azure Cosmos DB tem até 20% de taxa de transferência aprimorada, modo direto baseado em TCP e suporte para os recursos de serviço de back-end mais recentes, recomendamos que você atualize para a v4 na próxima oportunidade. Continue lendo abaixo para saber mais.

Atualize para o SDK Java do Azure Cosmos DB mais recente para obter o melhor do que o Azure Cosmos DB tem a oferecer - um serviço de banco de dados não relacional gerenciado com desempenho competitivo, disponibilidade de cinco noves, governança de recursos única e muito mais. Este artigo explica como atualizar seu aplicativo Java existente que está usando um SDK Java do Azure Cosmos DB mais antigo para o SDK Java 4.0 do Azure Cosmos DB mais recente para API para NoSQL. O SDK Java v4 do Azure Cosmos DB corresponde ao com.azure.cosmos pacote. Você pode usar as instruções neste documento se estiver migrando seu aplicativo de qualquer um dos seguintes SDKs Java do Azure Cosmos DB:

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

Azure Cosmos DB Java SDK e mapeamentos de pacotes

A tabela a seguir lista diferentes SDKs Java do Azure Cosmos DB, o nome do pacote e as informações de versão:

SDK Java Data de Lançamento APIs agrupadas Jarra Maven Nome do pacote Java Referência de API Release Notes (Notas de Lançamento) Data de aposentação
Assíncrono 2.x.x Junho de 2018 Async(RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx API Notas de Versão 31 de agosto de 2024
Sincronização 2.x.x Setembro de 2018 Sync com.microsoft.azure::azure-documentdb com.microsoft.azure.cosmosdb API 29 de fevereiro de 2024
3.x.x Julho de 2019 Async(Reator)/Sync com.microsoft.azure::azure-cosmos com.azure.data.cosmos API - 31 de agosto de 2024
4.0 Junho de 2020 Async(Reator)/Sync com.azure::azure-cosmos com.azure.cosmos API - -

Alterações na implementação do nível SDK

A seguir estão as principais diferenças de implementação entre diferentes SDKs:

RxJava é substituído por reator no SDK Java do Azure Cosmos DB versões 3.x.x e 4.0

Se você não estiver familiarizado com programação assíncrona ou programação reativa, consulte o guia de padrão do reator para obter uma introdução à programação assíncrona e ao Project Reator. Este guia pode ser útil se você tiver usado o Azure Cosmos DB Sync Java SDK 2.x.x ou o Azure Cosmos DB Java SDK 3.x.x Sync API no passado.

Se você estiver usando o Azure Cosmos DB Async Java SDK 2.x.x e planeja migrar para o SDK 4.0, consulte o Guia Reator vs RxJava para obter orientação sobre como converter o código RxJava para usar o Reator.

O SDK Java v4 do Azure Cosmos DB tem o modo de conectividade direta nas APIs Async e Sync

Se você estiver usando o SDK Java 2.x.x do Azure Cosmos DB Sync, observe que o modo de conexão direta baseado em TCP (em oposição ao HTTP) é implementado no Azure Cosmos DB Java SDK 4.0 para as APIs Async e Sync.

Alterações no nível da API

A seguir estão as alterações de nível de API no Azure Cosmos DB Java SDK 4.x.x em comparação com SDKs anteriores (Java SDK 3.x.x, Async Java SDK 2.x.x e Sync Java SDK 2.x.x):

Convenções de nomenclatura do SDK Java do Azure Cosmos DB

  • O SDK Java 3.x.x e 4.0 do Azure Cosmos DB refere-se aos recursos do cliente como Cosmos<resourceName>. Por exemplo, CosmosClient, , CosmosContainerCosmosDatabase. Enquanto na versão 2.x.x, os SDKs Java do Azure Cosmos DB não têm um esquema de nomenclatura uniforme.

  • O Azure Cosmos DB Java SDK 3.x.x e 4.0 oferece APIs Sync e Async.

    • Java SDK 4.0 : Todas as classes pertencem à API de sincronização, a menos que o nome da classe seja acrescentado com Async after Cosmos.

    • Java SDK 3.x.x: Todas as classes pertencem à API assíncrona, a menos que o nome da classe seja acrescentado com Async after Cosmos.

    • Async Java SDK 2.x.x: Os nomes das classes são semelhantes ao Sync Java SDK 2.x.x, no entanto, o nome começa com Async.

Estrutura hierárquica da API

O SDK Java 4.0 e 3.x.x do Azure Cosmos DB introduz uma estrutura de API hierárquica que organiza os clientes, bancos de dados e contêineres de forma aninhada, conforme mostrado no seguinte trecho de código do SDK 4.0:

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

Na versão 2.x.x do SDK Java do Azure Cosmos DB, todas as operações em recursos e documentos são executadas por meio da instância do cliente.

Representação de documentos

No Azure Cosmos DB Java SDK 4.0, POJO personalizados e JsonNodes são as duas opções para ler e gravar os documentos do Azure Cosmos DB.

No SDK Java 3.x.x do Azure Cosmos DB, o CosmosItemProperties objeto é exposto pela API pública e servido como uma representação de documento. Essa classe não é mais exposta publicamente na versão 4.0.

Importações

  • Os pacotes do Azure Cosmos DB Java SDK 4.0 começam com com.azure.cosmos

  • Os pacotes do Azure Cosmos DB Java SDK 3.x.x começam com com.azure.data.cosmos

  • Os pacotes da API de sincronização do Azure Cosmos DB Java SDK 2.x.x começam com com.microsoft.azure.documentdb

  • O Azure Cosmos DB Java SDK 4.0 coloca várias classes em um pacote com.azure.cosmos.modelsaninhado. Alguns desses pacotes incluem:

    • CosmosContainerResponse
    • CosmosDatabaseResponse
    • CosmosItemResponse
    • Os análogos da API Async para todos os pacotes acima
    • CosmosContainerProperties
    • FeedOptions
    • PartitionKey
    • IndexingPolicy
    • IndexingMode ... Etc.

Acessores

O Azure Cosmos DB Java SDK 4.0 expõe get e set métodos para acessar os membros da instância. Por exemplo, a CosmosContainer instância tem container.getId() e container.setId() métodos.

Isso é diferente do SDK Java 3.x.x do Azure Cosmos DB, que expõe uma interface fluente. Por exemplo, uma CosmosSyncContainer instância tem container.id() que está sobrecarregada para obter ou definir o id valor.

Gerenciando conflitos de dependência

A atualização do SDK Java V2 para V4 do Azure Cosmos DB pode introduzir conflitos de dependência devido a alterações nas bibliotecas usadas pelo SDK. A resolução destes conflitos exige uma gestão cuidadosa das dependências.

  1. Entenda as novas dependências: o SDK do Azure Cosmos DB V4 tem seu próprio conjunto de dependências que podem ser diferentes daquelas em versões anteriores. Certifique-se de que está ciente destas dependências:

    • 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. Remover dependências conflitantes: comece removendo as dependências relacionadas a versões anteriores do SDK do seu pom.xml arquivo. Isso inclui azure-cosmosdb e quaisquer dependências transitivas que o SDK antigo possa ter tido.

  3. Adicionar dependências do SDK V4: adicione o SDK V4 e suas dependências ao .pom.xml Eis um exemplo:

    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-cosmos</artifactId>
        <version>4.x.x</version> <!-- Use the latest version available -->
    </dependency>
    
  4. Verificar conflitos de dependência: use o comando Maven dependency:tree para gerar uma árvore de dependência e identificar quaisquer conflitos. Executar:

    mvn dependency:tree
    

    Procure por versões conflitantes de dependências. Esses conflitos geralmente ocorrem com bibliotecas como reactor-core, netty-handler, guavae jackson.

  5. Usar o Gerenciamento de Dependência: Se você encontrar conflitos de versão, talvez seja necessário substituir versões problemáticas usando a <dependencyManagement> seção no .pom.xml Aqui está um exemplo para impor uma versão específica do 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. Excluir dependências transitivas: Às vezes, talvez seja necessário excluir dependências transitivas trazidas por outras dependências. Por exemplo, se outra biblioteca traz uma versão mais antiga de uma dependência que entra em conflito, você pode excluí-la assim:

    <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. Reconstruir e testar: Depois de fazer essas alterações, reconstrua seu projeto e teste-o completamente para garantir que as novas dependências funcionem corretamente e que não ocorram conflitos de tempo de execução.

Comparações de trechos de código

Criar recursos

O trecho de código a seguir mostra as diferenças em como os recursos são criados entre as APIs 4.0, 3.x.x Async, 2.x.x Sync e 2.x.x Async:


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

Operações de item

O trecho de código a seguir mostra as diferenças em como as operações de item são executadas entre as APIs 4.0, 3.x.x Async, 2.x.x Sync e 2.x.x Async:


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

Indexação

O trecho de código a seguir mostra as diferenças em como a indexação é criada entre as APIs Async 4.0, 3.x.x Sync, 2.x.x Sync e 2.x.x Async:


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

Procedimentos armazenados

O trecho de código a seguir mostra as diferenças em como os procedimentos armazenados são criados entre as APIs Async 4.0, 3.x.x Sync, 2.x.x Sync e 2.x.x Async:


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

Feed de alterações

O trecho de código a seguir mostra as diferenças em como as operações de alimentação de alterações são executadas entre as APIs assíncronas 4.0 e 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();

Tempo de vida útil (TTL) no nível do contêiner

O trecho de código a seguir mostra as diferenças em como criar tempo de vida para dados no contêiner entre as APIs 4.0, 3.x.x Async, 2.x.x Sync e 2.x.x Async:


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

Nível de item Time-To-Live(TTL)

O trecho de código a seguir mostra as diferenças em como criar tempo de vida para um item entre as APIs 4.0, 3.x.x Async, 2.x.x Sync e 2.x.x Async:


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

Próximos passos