Sdílet prostřednictvím


Migrace aplikace pro použití sady Java SDK služby Azure Cosmos DB v4

PLATÍ PRO: NoSQL

Důležité

Vzhledem k tomu, že sada Azure Cosmos DB Java SDK v4 má až 20 % vyšší propustnost, přímý režim založený na protokolu TCP a podporu nejnovějších funkcí back-endové služby, doporučujeme upgradovat na verzi 4 na další příležitost. Další informace najdete níže.

Aktualizujte na nejnovější sadu Java SDK služby Azure Cosmos DB, abyste získali to nejlepší z toho, co Azure Cosmos DB nabízí – spravovanou nerelační databázovou službu s konkurenčním výkonem, dostupností s pěti devítkami, jedinečným řízením zdrojů a dalšími výhodami. Tento článek vysvětluje, jak upgradovat stávající aplikaci Java, která používá starší sadu Java SDK služby Azure Cosmos DB na novější sadu Java SDK služby Azure Cosmos DB 4.0 pro rozhraní API for NoSQL. Sada Azure Cosmos DB Java SDK v4 odpovídá com.azure.cosmos balíčku. Pokyny v tomto dokumentu můžete použít, pokud migrujete aplikaci z některé z následujících sad Java SDK služby Azure Cosmos DB:

  • Synchronizace sady Java SDK 2.x.x
  • Async Java SDK 2.x.x
  • Java SDK 3.x.x

Mapování balíčků a sad Java SDK služby Azure Cosmos DB

V následující tabulce jsou uvedeny různé sady Java SDK služby Azure Cosmos DB, název balíčku a informace o verzi:

Java SDK Datum vydání Sbalené rozhraní API Maven Jar Název balíčku Java Referenční příručka API Poznámky k verzi Datum odchodu do důchodu
Async 2.x.x červen 2018 Async(RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx Rozhraní API Poznámky k verzi sobota 31. srpna 2024
Sync 2.x.x Září 2018 Synchronizace com.microsoft.azure::azure-documentdb com.microsoft.azure.cosmosdb Rozhraní API čtvrtek 29. února 2024
3.x.x Červenec 2019 Async(Reactor)/Synchronizace com.microsoft.azure::azure-cosmos com.azure.data.cosmos Rozhraní API - sobota 31. srpna 2024
4.0 Červen 2020 Async(Reactor)/Synchronizace com.azure::azure-cosmos com.azure.cosmos Rozhraní API - -

Změny implementace na úrovni sady SDK

Toto jsou klíčové rozdíly v implementaci mezi různými sadami SDK:

RxJava se nahrazuje reaktorem v sadě Java SDK služby Azure Cosmos DB verze 3.x.x a 4.0.

Pokud neznáte asynchronní programování nebo reaktivní programování, přečtěte si průvodce vzorem Reactor, kde najdete úvod do asynchronního programování a projektu Reactor. Tato příručka může být užitečná, pokud jste v minulosti používali synchronizační sadu Java SDK služby Azure Cosmos DB 2.x.x nebo Sadu Java SDK služby Azure Cosmos DB 3.x.x Sync API.

Pokud používáte sadu Azure Cosmos DB Async Java SDK 2.x.x a plánujete migraci na sadu SDK verze 4.0, podívejte se do příručky Reactor vs RxJava Guide pro pokyny k převodu kódu RxJava na použití Reactor.

Sada Azure Cosmos DB Java SDK v4 má režim přímého připojení v asynchronních i synchronizačních rozhraních API.

Pokud jste používali sadu Java SDK pro synchronizaci služby Azure Cosmos DB 2.x.x, mějte na paměti, že režim přímého připojení založený na protokolu TCP (na rozdíl od protokolu HTTP) je implementovaný v sadě Azure Cosmos DB Java SDK 4.0 pro asynchronní i synchronizační rozhraní API.

Změny na úrovni rozhraní API

Níže jsou uvedené změny na úrovni rozhraní API v sadě Azure Cosmos DB Java SDK 4.x.x v porovnání s předchozími sadami SDK (Java SDK 3.x.x, Async Java SDK 2.x.x a Sync Java SDK 2.x.x):

Zásady vytváření názvů sady Java SDK služby Azure Cosmos DB

  • Verze Azure Cosmos DB Java SDK 3.x.x a 4.0 označují klientské prostředky jako Cosmos<resourceName>. Například , CosmosClient, CosmosDatabaseCosmosContainer. Zatímco ve verzi 2.x.x nemají sady Java SDK služby Azure Cosmos DB jednotné schéma pojmenování.

  • Sada Azure Cosmos DB Java SDK 3.x.x a 4.0 nabízí jak synchronní, tak asynchronní rozhraní API.

    • Java SDK 4.0 : Všechny třídy patří do synchronizačního rozhraní API, pokud není název třídy připojen Async za Cosmos.

    • Java SDK 3.x.x: Všechny třídy patří do asynchronního rozhraní API, pokud není název třídy připojen Async za Cosmos.

    • Async Java SDK 2.x.x: Názvy tříd jsou podobné Sync Java SDK 2.x.x, ale název začíná Async.

Hierarchická struktura rozhraní API

Sada Azure Cosmos DB Java SDK 4.0 a 3.x.x zavádí hierarchickou strukturu rozhraní API, která uspořádá klienty, databáze a kontejnery vnořeným způsobem, jak je znázorněno v následujícím fragmentu kódu sady SDK 4.0:

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

Ve verzi 2.x.x sady Azure Cosmos DB Java SDK se všechny operace s prostředky a dokumenty provádějí prostřednictvím instance klienta.

Reprezentace dokumentů

Ve službě Azure Cosmos DB Java SDK 4.0 jsou vlastní POJO a JsonNodes dvě možnosti pro čtení a zápis dokumentů ze služby Azure Cosmos DB.

V sadě Azure Cosmos DB Java SDK 3.x.x CosmosItemProperties je objekt zpřístupněn veřejným rozhraním API a slouží jako reprezentace dokumentu. Tato třída již není veřejně zpřístupněna ve verzi 4.0.

Importy

  • Balíčky Java SDK 4.0 pro Azure Cosmos DB začínají na com.azure.cosmos

  • Balíčky Java SDK Azure Cosmos DB verze 3.x.x začínají s com.azure.data.cosmos

  • Balíčky rozhraní API pro synchronizaci sady Azure Cosmos DB Java SDK 2.x.x začínají na com.microsoft.azure.documentdb

  • Sada Azure Cosmos DB Java SDK 4.0 umístí několik tříd do vnořeného balíčku com.azure.cosmos.models. Mezi tyto balíčky patří:

    • CosmosContainerResponse
    • CosmosDatabaseResponse
    • CosmosItemResponse
    • Analogy asynchronního rozhraní API pro všechny výše uvedené balíčky
    • CosmosContainerProperties
    • FeedOptions
    • PartitionKey
    • IndexingPolicy
    • IndexingMode ... atd.

Přístupové objekty

Sada Azure Cosmos DB Java SDK 4.0 zveřejňuje get a set metody pro přístup k členům instance. Například instance CosmosContainercontainer.getId() a container.setId() metody.

Liší se od sady Azure Cosmos DB Java SDK 3.x.x, která zveřejňuje plynulé rozhraní. Například instance CosmosSyncContainercontainer.id(), což je přetížené pro získání nebo nastavení hodnoty id.

Správa konfliktů závislostí

Upgrade ze sady Azure Cosmos DB Java SDK V2 na V4 může představovat konflikty závislostí kvůli změnám knihoven používaných sadou SDK. Řešení těchto konfliktů vyžaduje pečlivou správu závislostí.

  1. Seznamte se s novými závislostmi: Sada SDK služby Azure Cosmos DB V4 má svou vlastní sadu závislostí, které se můžou lišit od těch v předchozích verzích. Ujistěte se, že znáte tyto závislosti:

    • 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. Odebrat konfliktní závislosti: Začněte odebráním závislostí souvisejících s předchozími verzemi sady SDK z vašeho pom.xml souboru. Patří sem azure-cosmosdb i všechny přechodné závislosti, které mohla mít stará sada SDK.

  3. Přidání závislostí sady SDK V4: Přidejte sadu SDK V4 a její závislosti do vašeho pom.xml. Tady je příklad:

    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-cosmos</artifactId>
        <version>4.x.x</version> <!-- Use the latest version available -->
    </dependency>
    
  4. dependency:tree strom závislostí a identifikujte případné konflikty. Run (Spuštění):

    mvn dependency:tree
    

    Vyhledejte všechny konfliktní verze závislostí. K těmto konfliktům často dochází u knihoven, jako jsou reactor-core, netty-handler, guava a jackson.

  5. Použijte správu závislostí: Pokud narazíte na konflikty verzí, můžete problematické verze přepsat pomocí <dependencyManagement> oddílu ve vašem pom.xml. Tady je příklad vynucení konkrétní verze 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. Vyloučit tranzitivní závislosti: Někdy může být nutné vyloučit tranzitivní závislosti, které jsou přeneseny jinými závislostmi. Pokud například jiná knihovna přináší starší verzi závislosti, která koliduje, můžete ji vyloučit takto:

    <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. Opětovné sestavení a testování: Po provedení těchto změn znovu sestavte projekt a důkladně ho otestujte, aby nové závislosti fungovaly správně a nedošlo ke konfliktům za běhu.

Porovnání fragmentů kódu

Vytvoření zdrojů

Následující úryvek kódu ukazuje rozdíly ve způsobu vytváření prostředků mezi rozhraními API 4.0 Asynchronous, 3.x.x Asynchronous, 2.x.x Synchronous a 2.x.x Asynchronous.


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

Operace položek

Následující fragment kódu ukazuje rozdíly v tom, jak se operace položek provádějí mezi API verzemi 4.0, 3.x.x Asynchronní, 2.x.x Synchronní a 2.x.x Asynchronní.


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

Indexování

Následující fragment kódu ukazuje rozdíly ve vytváření indexování mezi API 4.0 Async, 3.x.x Async, 2.x.x Sync a 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);

Uložené procedury

Následující fragment kódu ukazuje rozdíly v tom, jak se uložené procedury vytvářejí mezi 4.0, 3.x.x Async, 2.x.x Sync a 2.x.x Async API:


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

Změna kanálu

Následující fragment kódu ukazuje rozdíly v tom, jak se operace toku změn provádějí mezi asynchronními API verze 4.0 a 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.boundedElastic())
        .subscribe();

TTL (Time to Live) na úrovni kontejneru

Následující fragment kódu ukazuje rozdíly v tom, jak vytvořit čas životnosti pro data v kontejneru mezi API 4.0, 3.x.x Async, 2.x.x Sync a 2.x.x Async API.


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

Hodnota TTL (Time-To-Live) na úrovni položky

Následující fragment kódu ukazuje rozdíly v tom, jak vytvořit čas života pro položku mezi rozhraními API 4.0, 3.x.x Async, 2.x.x Sync a 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
);

Další kroky