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, pěti devítkou dostupností, zásadami správného řízení prostředků typu a dalšími prostředky. 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 sady 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í dokumentace ke knihovně API Poznámky k verzi Datum vyřazení
Async 2.x.x 2018. června Async(RxJava) com.microsoft.azure::azure-cosmosdb com.microsoft.azure.cosmosdb.rx Rozhraní API Poznámky k verzi sobota 31. srpna 2024
Synchronizace 2.x.x Září 2018 Sync 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, přečtěte si příručku Reactor vs. Průvodce RxJava a 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):

Azure Cosmos DB Java SDK naming conventions

  • Sada Azure Cosmos DB Java SDK 3.x.x a 4.0 odkazují na 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í rozhraní API pro synchronizaci i 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 čtení a zápisu 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 Sady Java SDK 4.0 služby Azure Cosmos DB začínají na com.azure.cosmos

  • Balíčky Sady Java SDK služby Azure Cosmos DB 3.x.x začínají na 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 fluent rozhraní. Například CosmosSyncContainer instance má container.id() přetížení získat nebo nastavit id hodnotu.

Porovnání fragmentů kódu

Vytvoření zdrojů

Následující fragment kódu ukazuje rozdíly ve způsobu vytváření prostředků mezi asynchronními rozhraními API 4.0, 3.x.x, 2.x.x Sync a 2.x.x:


// 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 asynchronními rozhraními API 4.0, 3.x.x, 2.x.x Sync a 2.x.x:


// 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 v tom, jak se indexování vytváří mezi asynchronními rozhraními API 4.0, 3.x.x, 2.x.x Sync a 2.x.x:


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 asynchronními rozhraními API 4.0, 3.x.x, 2.x.x Sync a 2.x.x:


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 kanálu změn provádějí mezi rozhraními API 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.elastic())
        .subscribe();

TTL (Time to Live) na úrovni kontejneru

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


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 dobu, která se má pro položku živě spustit mezi rozhraními API 4.0, 3.x.x, 2.x.x Sync a 2.x.x asynchronními rozhraními API:


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