Condividi tramite


Eseguire la migrazione dell'applicazione per usare Azure Cosmos DB Java SDK v4

SI APPLICA A: NoSQL

Importante

Per altre informazioni su questo SDK, vedere le note sulla versione di Azure Cosmos DB Java SDK v4, il repository Maven, i suggerimenti sulle prestazioni di Azure Cosmos DB Java SDK v4 e la guida alla risoluzione dei problemi di Azure Cosmos DB Java SDK v4.

Importante

Poiché Azure Cosmos DB Java SDK v4 ha fino al 20% di velocità effettiva avanzata, modalità diretta basata su TCP e supporto per le funzionalità più recenti del servizio back-end, è consigliabile eseguire l'aggiornamento alla versione 4 alla prima opportunità. Continuare a leggere per altre informazioni.

Eseguire l'aggiornamento all'SDK Java di Azure Cosmos DB più recente per ottenere il meglio di ciò che Azure Cosmos DB ha da offrire: un servizio di database non relazionale gestito con prestazioni competitive, disponibilità cinque nove, governance delle risorse unica e altro ancora. Questo articolo illustra come aggiornare l'applicazione Java esistente basata sul precedente Azure Cosmos DB Java SDK al nuovo Azure Cosmos DB Java SDK 4.0 per API for NoSQL. Azure Cosmos DB Java SDK v4 corrisponde al pacchetto com.azure.cosmos. È possibile usare le istruzioni riportate in questo documento si esegue la migrazione dell'applicazione da una delle edizioni di Azure Cosmos DB Java SDK seguenti:

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

Mapping di Azure Cosmos DB Java SDK e dei pacchetti

La tabella seguente elenca i diversi Azure Cosmos DB Java SDK, il nome del pacchetto corrispondente e informazioni sulla versione:

SDK per Java Data di rilascio API in bundle Jar Maven Nome pacchetto Java Riferimento API Note sulla versione Data del ritiro
Async 2.x.x 2018 giugno Async(RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx API Note sulla versione sabato 31 agosto 2024
Sync 2.x.x Settembre 2018 Sync com.microsoft.azure::azure-documentdb com.microsoft.azure.cosmosdb API 29 febbraio 2024
3.x.x Luglio 2019 Async(Reactor)/Sync com.microsoft.azure::azure-cosmos com.azure.data.cosmos API - sabato 31 agosto 2024
4.0 Giugno 2020 Async(Reactor)/Sync com.azure::azure-cosmos com.azure.cosmos API - -

Modifiche di implementazione a livello di SDK

Di seguito sono illustrate le principali differenze di implementazione tra i vari SDK:

RxJava è stato sostituito con Reactor in Azure Cosmos DB Java SDK versioni 3.x.x e 4.0

Se non si ha familiarità con la programmazione asincrona o reattiva, vedere la guida introduttiva ai modelli di Reactor per un'introduzione alla programmazione asincrona e a Project Reactor. Questa guida può essere utile se in passato si è usata l'API Sync per Azure Cosmos DB Sync Java SDK 2.x.x o Azure Cosmos DB Java SDK 3.x.x.

Se si usa Azure Cosmos DB Async Java SDK 2.x.x e si prevede di eseguire la migrazione a 4.0 SDK, vedere la guida relativa al confronto tra Reactor e RxJava per istruzioni su come convertire codice RxJava per poter usare Reactor.

Azure Cosmos DB Java SDK v4 integra la modalità di connettività diretta sia nell'API asincrona che nell'API sincrona

Se si usa Azure Cosmos DB Sync Java SDK 2.x.x, tenere presente che la modalità di connessione diretta basata su TCP (anziché HTTP) viene implementata in Azure Cosmos DB Java SDK 4.0 sia per l'API asincrona che per l'API sincrona.

Modifiche al livello di API

Di seguito sono illustrate le modifiche a livello di API introdotte in Azure Cosmos DB Java SDK 4.x.x rispetto ai precedenti SDK (Java SDK 3.x.x, Async Java SDK 2.x.x e Sync Java SDK 2.x.x):

Convenzioni di denominazione di Azure Cosmos DB Java SDK

  • Azure Cosmos DB Java SDK 3.x.x e 4.0 fanno riferimento alle risorse client come Cosmos<resourceName>. Ad esempio CosmosClient, CosmosDatabase, CosmosContainer. Nella versione 2.x.x, invece, Azure Cosmos DB Java SDK non aveva uno schema di denominazione uniforme.

  • Azure Cosmos DB Java SDK 3.x.x e 4.0 offrono sia API asincrone sia API sincrone.

    • Java SDK 4.0: tutte le classi appartengono all'API sincrona, a meno che nel nome della classe non sia stato aggiunto Async dopo Cosmos.

    • Java SDK 3.x.x: tutte le classi appartengono all'API asincrona, a meno che nel nome della classe non sia stato aggiunto Async dopo Cosmos.

    • Java SDK 2.x.x asincrona: i nomi delle classi sono simili a Java SDK 2.x.x sincrona, tuttavia, il nome inizia con Async.

Struttura dell'API gerarchica

Azure Cosmos DB Java SDK 4.0 e 3.x.x introducono una struttura dell'API gerarchica che organizza i client, i database e i contenitori in modo annidato, come illustrato nel frammento di codice 4.0 SDK seguente:

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

Nella versione 2.x.x di Azure Cosmos DB Java SDK, tutte le operazioni su risorse e documenti vengono eseguite tramite l'istanza del client.

Rappresentazione di documenti

In Azure Cosmos DB Java SDK 4.0, i POJO personalizzati e JsonNodes sono le due opzioni disponibili per leggere e scrivere documenti da Azure Cosmos DB.

In Azure Cosmos DB Java SDK 3.x.x, l'oggetto CosmosItemProperties viene esposto dall'API pubblica e restituito come rappresentazione del documento. Questa classe non è più esposta pubblicamente nella versione 4.0.

Importazioni

  • I pacchetti Azure Cosmos DB Java SDK 4.0 iniziano con com.azure.cosmos

  • I pacchetti Azure Cosmos DB Java SDK 3.x.x iniziano con com.azure.data.cosmos

  • I pacchetti Azure Cosmos DB Java SDK 2.x.x iniziano con com.microsoft.azure.documentdb

  • Azure Cosmos DB Java SDK 4.0 inserisce più classi in un pacchetto annidato com.azure.cosmos.models. Alcuni di questi pacchetti includono:

    • CosmosContainerResponse
    • CosmosDatabaseResponse
    • CosmosItemResponse
    • Tutti i pacchetti precedenti si applicano anche all'API asincrona
    • CosmosContainerProperties
    • FeedOptions
    • PartitionKey
    • IndexingPolicy
    • IndexingMode ...e così via.

Funzioni di accesso

Azure Cosmos DB Java SDK 4.0 espone i metodi get e set per accedere ai membri dell'istanza. L'istanza CosmosContainer, ad esempio, include i metodi container.getId() e container.setId().

Questo è un aspetto che differisce da Azure Cosmos DB Java SDK 3.x.x, che espone un'interfaccia Fluent. Un'istanza CosmosSyncContainer, ad esempio, include container.id(), che viene sottoposto a overload per ottenere o impostare il valore di id.

Confronti tra frammenti di codice

Creare le risorse

Il frammento di codice seguente mostra le differenze nella modalità di creazione delle risorse tra le API 4.0, 3.x.x asincrona, 2.x.x sincrona e 2.x.x asincrona:


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

Operazioni sugli elementi

Il frammento di codice seguente mostra le differenze nella modalità di esecuzione delle operazioni sugli elementi tra le API 4.0, 3.x.x asincrona, 2.x.x sincrona a 2.x.x asincrona:


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

Indicizzazione

Il frammento di codice seguente mostra le differenze nella modalità di creazione dell'indicizzazione tra le API 4.0, 3.x.x asincrona, 2.x.x sincrona e 2.x.x asincrona:


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 procedure

Il frammento di codice seguente mostra le differenze nella modalità di creazione delle stored procedure tra le API 4.0, 3.x.x asincrona, 2.x.x sincrona e 2.x.x asincrona:


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 delle modifiche

Il frammento di codice seguente mostra le differenze nella modalità di esecuzione delle operazioni sui feed di modifiche tra le API asincrone 3.x.x e 4.0:


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

Durata (TTL) predefinita a livello di contenitore

Il frammento di codice seguente mostra le differenze nella modalità di creazione dei dati di durata (Time-To-Live) nel container tra le API 4.0, 3.x.x asincrona, 2.x.x sincrona e 2.x.x asincrona:


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

Durata (TTL) predefinita a livello di elemento

Il frammento di codice seguente mostra le differenze nella modalità di creazione dei dati di durata (Time-To-Live) per un elemento tra le API 4.0, 3.x.x asincrona, 2.x.x sincrona e 2.x.x asincrona:


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

Passaggi successivi