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):
Azure Cosmos DB Java SDK 3.x.x e 4.0 fanno riferimento alle risorse client come
Cosmos<resourceName>
. Ad esempioCosmosClient
,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
dopoCosmos
.Java SDK 3.x.x: tutte le classi appartengono all'API asincrona, a meno che nel nome della classe non sia stato aggiunto
Async
dopoCosmos
.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
.
Gestione dei conflitti di dipendenza
L'aggiornamento da Azure Cosmos DB Java SDK V2 a V4 può introdurre conflitti di dipendenza a causa delle modifiche apportate alle librerie usate dall'SDK. La risoluzione di questi conflitti richiede un'attenta gestione delle dipendenze.
Informazioni sulle nuove dipendenze: Azure Cosmos DB V4 SDK ha un proprio set di dipendenze che potrebbero essere diverse da quelle nelle versioni precedenti. Assicurarsi di conoscere queste dipendenze:
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
Rimuovere dipendenze in conflitto: iniziare rimuovendo le dipendenze correlate alle versioni precedenti dell'SDK dal file
pom.xml
. Questi includonoazure-cosmosdb
ed eventuali dipendenze transitive che l'SDK precedente avrebbe potuto avere.Aggiungere le dipendenze dell'SDK V4: aggiungere l'SDK V4 e le relative dipendenze al
pom.xml
. Ecco un esempio:<dependency> <groupId>com.azure</groupId> <artifactId>azure-cosmos</artifactId> <version>4.x.x</version> <!-- Use the latest version available --> </dependency>
Controllare i conflitti di dipendenza: usare il comando
dependency:tree
Maven per generare un albero delle dipendenze e identificare eventuali conflitti. Eseguire:mvn dependency:tree
Cercare eventuali versioni in conflitto delle dipendenze. Questi conflitti si verificano spesso con librerie come
reactor-core
,netty-handler
,guava
ejackson
.UsareGestione dipendenze: se si verificano conflitti di versione, potrebbe essere necessario eseguire l'override delle versioni problematiche usando la sezione
<dependencyManagement>
inpom.xml
. Di seguito è riportato un esempio per applicare una versione specifica direactor-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>
Escludere dipendenze transitive: a volte potrebbe essere necessario escludere dipendenze transitive causate da altre dipendenze. Ad esempio, se un'altra libreria inserisce una versione precedente di una dipendenza in conflitto, è possibile escluderla come segue:
<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>
Ricompilare e testare: dopo aver apportato queste modifiche, ricompilare il progetto e testarlo accuratamente per assicurarsi che le nuove dipendenze funzionino correttamente e che non si verifichino conflitti di runtime.
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:
- API asincrona per Java SDK 4.0
- API asincrona per Java SDK 3.x.x
- API Java SDK 2.x.x sincrona
- API Java SDK 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:
- API asincrona per Java SDK 4.0
- API asincrona per Java SDK 3.x.x
- API Java SDK 2.x.x sincrona
- API Java SDK 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:
- API asincrona per Java SDK 4.0
- API asincrona per Java SDK 3.x.x
- API Java SDK 2.x.x sincrona
- API Java SDK 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:
- API asincrona per Java SDK 4.0
- API asincrona per Java SDK 3.x.x
- API Java SDK 2.x.x sincrona
- API Java SDK 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:
- API asincrona per Java SDK 4.0
- API asincrona per Java SDK 3.x.x
- API Java SDK 2.x.x sincrona
- API Java SDK 2.x.x asincrona
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:
- API asincrona per Java SDK 4.0
- API asincrona per Java SDK 3.x.x
- API Java SDK 2.x.x sincrona
- API Java SDK 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:
- API asincrona per Java SDK 4.0
- API asincrona per Java SDK 3.x.x
- API Java SDK 2.x.x sincrona
- API asincrona per Java SDK 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
);
Passaggi successivi
- Compilare un'app Java per gestire i dati di Azure Cosmos DB for NoSQL tramite V4 SDK
- Informazioni sugli SDK Java basati su Reactor
- Informazioni sulla conversione di codice asincrono RxJava in codice asincrono Reactor con la guida relativa al confronto tra Reactor e RxJava
- Si sta tentando di pianificare la capacità per una migrazione ad Azure Cosmos DB?
- Se si conosce solo il numero di vcore e server nel cluster di database esistente, leggere le informazioni sulla stima delle unità richieste usando vCore o vCPU
- Se si conosce la frequenza delle richieste tipiche per il carico di lavoro corrente del database, leggere le informazioni sulla stima delle unità richieste con lo strumento di pianificazione della capacità di Azure Cosmos DB