Oefening: NoSQL-gegevens programmatisch maken, lezen, bijwerken en verwijderen

Voltooid

U hebt de verbinding naar Azure Cosmos DB gemaakt. In deze eenheid gaat u gebruikersdocumenten in uw WebCustomers-verzameling maken. Vervolgens haalt u de documenten op per ID, vervangt u ze en verwijdert u ze.

Programmatisch werken met documenten

Gegevens zijn opgeslagen in JSON-documenten in Azure Cosmos DB. Documenten in de portal kunnen programmatisch worden gemaakt, opgehaald, vervangen of verwijderd. Dit lab gaat over programmatische bewerkingen. Azure Cosmos DB biedt SDK’s aan de clientzijde voor .NET, .NET Core, Java, Node.js en Python. Elk van deze SDK’s biedt ondersteuning voor deze bewerkingen. In deze module wordt gebruikgemaakt van de Java SDK om CRUD-bewerkingen (maken, ophalen, bijwerken en verwijderen) uit te voeren op NoSQL-gegevens die zijn opgeslagen in Azure Cosmos DB.

De belangrijkste bewerkingen voor Azure Cosmos DB-documenten zijn onderdeel van de klasse CosmosAsyncContainer:

Met upsert wordt een bewerking voor maken of vervangen uitgevoerd, afhankelijk van het feit of het document al bestaat.

Als u een van deze bewerkingen wilt uitvoeren, hebt u helperklassen (Java POJO-klassen) nodig die de objecten vertegenwoordigen die in de database zijn opgeslagen. Omdat we werken met een database met gebruikers, moet u een User-klasse instellen die gebruikersentiteiten vertegenwoordigt. Met deze klasse worden primaire gegevens opgeslagen, zoals voornaam, achternaam en gebruikers-ID. (De ID is vereist omdat dit de partitiesleutel is om horizontaal schalen mogelijk te maken.)

Omdat iedere gebruiker enkele gekoppelde verzendvoorkeuren en coupons heeft, kunt u ShippingPreference- en CouponsUsed-gegevenstypen gebruiken om deze entiteiten weer te geven. Tot slot kan iedere gebruiker een bestelgeschiedenis hebben die mogelijk niet gebonden is. U kunt daarom het beste afzonderlijke OrderHistory-entiteiten met een bijbehorende Java POJO-klasse gebruiken.

Ga naar src/main/Java/com/azure/Azure-Cosmos-Java-SQL-app-mslearn en zoek in de map gegevenstypen. U ziet een aantal POJO's: User, ShippingPreference, OrderHistory en CouponsUsed. Daarom hebben we alle entiteits-POJO's en hun helperklassen verstrekt.

Vervolgens maken we een aantal entiteiten en voeren we enkele eenvoudige CRUD-bewerkingen uit op de Azure Cosmos DB-container en de daarin opgenomen documenten. U kunt Azure Cosmos DB een Jackson-ObjectNode-instantie doorgeven die rechtstreeks het JSON-document opgeeft. Maar Azure Cosmos DB kan ook Java-POJO's naar JSON serialiseren. Aangezien dit de eenvoudigste aanpak is en er verder geen verschillen zijn, raden we deze methode aan.

Documenten maken

  1. Open User.java en bekijk de inhoud. Het ziet er ongeveer als volgt uit:

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.List;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class User {
    
        /** Document ID (required by Azure Cosmos DB). */
        private String id;
    
        /** User ID. */
        private String userId;
    
        /** User last name. */
        private String lastName;
    
        /** User first name. */
        private String firstName;
    
        /** User email address. */
        private String email;
    
        /** User dividend setting. */
        private String dividend;
    
        /** User shipping preferences. */
        private ShippingPreference shippingPreference;
    
        /** User order history. */
        private List<OrderHistory> orderHistory;
    
        /** Coupons recorded by the user. */
        private List<CouponsUsed> coupons;
    }
    

    Houd er rekening mee dat de toegangsmethoden voor de velden id, userId en andere velden impliciet zijn (dus niet gedefinieerd in code). Dit gedrag is mogelijk omdat we de annotatie Project Lombok @Data gebruiken om ze automatisch te maken.

    Met de annotatie @NoArgsConstructor wordt een constructor gegenereerd zonder argumenten voor het instellen van standaard veldwaarden. Met de annotatie @AllArgsConstructor wordt een andere constructor met een volledige set argumenten gegenereerd om alle veldwaarden rechtstreeks op te geven.

    Houd er rekening mee dat User een id-eigenschap heeft. Alle Azure Cosmos DB-documenten vereisen een id-eigenschap en daarom moeten alle POJO's die we willen serialiseren naar JSON-documenten, een id-veld bevatten.

  2. Voeg de volgende methode toe aan CosmosApp.java:

    /**
     * Take in list of Java POJOs, check if each exists, and if not insert it.
     * @param users List of User POJOs to insert.
     */
    private static void createUserDocumentsIfNotExist(final List<User> users) {
        Flux.fromIterable(users).flatMap(user -> {
            try {
                container.readItem(user.getId(), new PartitionKey(user.getUserId()), User.class).block();
                logger.info("User {} already exists in the database", user.getId());
                return Mono.empty();
            } catch (Exception err) {
                logger.info("Creating User {}", user.getId());
                return container.createItem(user, new PartitionKey(user.getUserId()), new CosmosItemRequestOptions());
            }
        }).blockLast();
    }
    
  3. Keer terug naar de methode basicOperations en voeg het volgende toe aan het einde van die methode, nog vóór de client.close()-aanroep.

    User maxaxam = new User(
        "1",
        "maxaxam",
        "Axam",
        "Max",
        "maxaxam@contoso.com",
        "2.0",
        new ShippingPreference(
            1,
            "90 W 8th St",
            "",
            "New York",
            "NY",
            "10001",
            "USA"
        ),
        new ArrayList<OrderHistory>(Arrays.asList(
            new OrderHistory(
                "3",
                "1000",
                "08/17/2018",
                "52.49"
            )
        )),
        new ArrayList<CouponsUsed>(Arrays.asList(
            new CouponsUsed(
                "A7B89F"
            )
        ))
    );
    
    User nelapin = new User(
            "2",
            "nelapin",
            "Pindakova",
            "Nela",
            "nelapin@contoso.com",
            "8.50",
            new ShippingPreference(
                1,
                "505 NW 5th St",
                "",
                "New York",
                "NY",
                "10001",
                "USA"
            ),
            new ArrayList<OrderHistory>(Arrays.asList(
                new OrderHistory(
                    "4",
                    "1001",
                    "08/17/2018",
                    "105.89"
                )
            )),
            new ArrayList<CouponsUsed>(Arrays.asList(
                new CouponsUsed(
                    "Fall 2018"
                )
            ))
    );
    
    createUserDocumentsIfNotExist(new ArrayList<User>(Arrays.asList(maxaxam, nelapin)));
    
  4. Zorg dat u CosmosApp.java bouwt en uitvoert in de IDE of voer het programma uit in de terminal met behulp van:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    Bij het maken van elk nieuw gebruikersdocument wordt uitvoer weergegeven op de terminal.

    INFO: Database and container validation complete
    INFO: Creating User 1
    INFO: Creating User 2
    

    Mogelijk wordt er ook extra tekst weergegeven die door de logger is verzonden, zoals timestamps.

Gefeliciteerd U hebt uw eerste gegevens in Azure Cosmos DB gemaakt vanuit een Java-toepassing. Laat we eens evalueren wat u hier hebt gedaan.

Er zijn drie nieuwe acties in basicOperations:

  1. Maak het maxaxam User-exemplaar.
  2. Maak het nelapin User-exemplaar.
  3. Roep createUserDocumentsIfNotExist aan en geef maxaxam en nelapin door als een lijst.

Met het aanroepen van createUserDocumentsIfNotExist worden beide User-instanties als items/documenten toegevoegd aan Azure Cosmos DB. Als u de User-instanties doorgeeft als een lijst, is het onze bedoeling om een performante methode te modelleren om met behulp van een minimum aan rekenresources snel POJO's in Azure Cosmos DB op te nemen. createUserDocumentsIfNotExist implementeert efficiënte asynchrone invoeging van een lijst met POJO's.

Stel dat ons doel is om het aantal aanvragen per seconde per thread te maximaliseren. Ter vergelijking, de synchronisatiebenadering voor het schrijven van createUserDocumentsIfNotExist, waarbij we de readItem-controle voorlopig negeren, is om te itereren over elk User-exemplaar in users. Voor elke User u maken we een blokkerende aanroep naar createItem:

container.createItem(u, new PartitionKey(u.getUserId()), new CosmosItemRequestOptions()).block(); // <= Note the .block() which loops until request response.

Deze synchronisatiestijl implementeert een intuïtief proces: aanvraag indienen, wachten op antwoord, volgende aanvraag indienen. createUserDocumentsIfNotExist gebruikt deze methode echter niet, omdat blokkerende aanroepen in feite CPU-cycli verspillen tijdens de reactietijd van de aanvraag, wat leidt tot een laag aantal aanvragen per seconde.

U kunt deze aanvragen/het tweede probleem omzeilen door meerdere threads te produceren om parallelle aanroepen voor het blokkeren van aanvragen te doen. De meerdere threads zorgen voor een betere uitvoering van de runtime. Maar als het uw doel is zuinig te zijn met threadresources, blijft dit een verspilling. Elke thread wordt opnieuw uitgevoerd tijdens de reactietijd van een aanvraag, terwijl de thread in plaats daarvan meerdere taken had kunnen verwerken voor iets anders, waardoor u per thread maar weinig aanvragen per seconde kunt sturen.

Daarom en omdat we u een threadefficiënte invoeging van Java POJO's willen tonen, hebben we in plaats daarvan een asynchroon voorbeeld van documentinvoeging gegeven. De ondersteuning voor Azure Cosmos DB Java SDK v4 is afkomstig van Project Reactor, een Java-toepassingsframework dat een stroomgebaseerd programmeermodel met declaratieve gegevensstromen biedt voor asynchroon, gebeurtenisgestuurd programmeren. Met createDocumentsIfNotExist wordt de asynchrone programmering van Project Reactor geïmplementeerd.

In createUserDocumentsIfNotExist is Flux.fromIterable(users) een Project Reactor-factory-methode. Er wordt een Flux-exemplaar gemaakt dat een bron is van asynchrone gebeurtenissen. In dit geval bevat elke asynchrone gebeurtenis een argument van het User-exemplaar. Het Flux-exemplaar bevat twee dergelijke gebeurtenissen, één voor maxaxam en één voor nelapin. De code in .flatMap( ... ).blockLast(); definieert een pijplijn van opeenvolgende bewerkingen die moeten worden uitgevoerd voor de gebeurtenissen die worden gegenereerd door het Flux-exemplaar.

Een van deze bewerkingen is createItem. Het idee is dat deze pijplijn bijna identiek is aan de synchrone implementatie, met dit verschil dat de createItem-aanroep niet blokkeren. Meer in het bijzonder betekent de aanroep van blockLast() een abonnement op de geassembleerde pijplijn, waardoor de Flux de twee eigen gebeurtenissen asynchroon uitvoert. Vervolgens wordt in de pijplijn binnen .flatMap( ... ).blockLast(); elk van deze gebeurtenissen op een pseudo-parallelle manier verwerkt. Wanneer een aanvraag is ingediend en er wordt gewacht op een reactie, verwerkt Project Reactor de andere aanvragen op de achtergrond, wat een essentiële factor is om het aantal aanvragen per seconde per thread te maximaliseren.

Nu we efficiënte asynchrone databaseaanvragen met Project Reactor hebben gedemonstreerd, worden er voor de rest van dit lab blokkerende (synchrone) aanroepen gebruikt om het proces eenvoudig te houden. Voor meer informatie over Project Reactor gaat u naar de handleiding voor Reactor-patronen van Azure Cosmos DB.

Documenten lezen

  1. Als u documenten uit de database wilt lezen, voegt u de volgende methode toe aan CosmosApp:

    /**
     * Take in a Java POJO argument, extract ID and partition key, and read the corresponding document from the container.
     * In this case the ID is the partition key.
     * @param user User POJO to pull ID and partition key from.
     */
    private static CosmosItemResponse<User> readUserDocument(final User user) {
        CosmosItemResponse<User> userReadResponse = null;
    
        try {
            userReadResponse = container.readItem(user.getId(), new PartitionKey(user.getUserId()), User.class).block();
            logger.info("Read user {}", user.getId());
        } catch (CosmosException de) {
            logger.error("Failed to read user {}", user.getId(), de);
        }
    
        return userReadResponse;
    }
    
  2. Kopieer en plak de volgende code aan het eind van de methode basicOperations, na de code voor het maken van het document:

    readUserDocument(maxaxam);
    
  3. Zorg dat u CosmosApp.java bouwt en uitvoert in de IDE of voer het programma uit in de terminal met behulp van:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    In de terminal wordt de volgende uitvoer weergegeven, waarbij 'Read user 1' aangeeft dat het document is opgehaald.

    INFO: Database and container validation complete
    INFO: User 1 already exists in the database
    INFO: User 2 already exists in the database
    INFO: Read user 1
    

    Mogelijk wordt er ook extra tekst weergegeven die is verzonden door de logger.

Documenten vervangen

Azure Cosmos DB biedt ondersteuning voor het vervangen van JSON-documenten. In dit geval werken we een gebruikersaccount bij vanwege een wijziging in de achternaam.

  1. Voeg in het bestand CosmosApp.java na de methode readUserDocument de methode replaceUserDocument toe.

    /**
     * Take in a Java POJO argument, extract ID and partition key,
     * and replace the existing document with the same ID and partition key to match.
     * @param user User POJO representing the document update.
     */
    private static void replaceUserDocument(final User user) {
        try {
            CosmosItemResponse<User> userReplaceResponse = container.replaceItem(user, user.getId(), new PartitionKey(user.getUserId())).block();
            logger.info("Replaced User {}", user.getId());
        } catch (CosmosException de) {
            logger.error("Failed to replace User {}", user.getUserId());
        }
    }
    
  2. Kopieer en plak de volgende code aan het einde van de basicOperations methode, na het lezen van de documentcode.

    maxaxam.setLastName("Suh");
    replaceUserDocument(maxaxam);
    
  3. Zorg dat u CosmosApp.java bouwt en uitvoert in de IDE of voer het programma uit in de terminal met behulp van:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    In de terminal wordt de volgende uitvoer weergegeven, waarbij 'Replaced last name for Suh' aangeeft dat het document is vervangen.

    INFO: Database and container validation complete
    INFO: User 1 already exists in the database
    INFO: User 2 already exists in the database
    INFO: Read user 1
    INFO: Replaced last name for Suh
    

Documenten verwijderen

  1. Kopieer en plak de deleteUserDocument-methode onder uw replaceUserDocument-methode.

    /**
     * Take in a Java POJO argument, extract ID and partition key,
     * and delete the corresponding document.
     * @param user User POJO representing the document update.
     */
    private static void deleteUserDocument(final User user) {
        try {
            container.deleteItem(user.getId(), new PartitionKey(user.getUserId())).block();
            logger.info("Deleted user {}", user.getId());
        } catch (CosmosException de) {
            logger.error("User {} could not be deleted.", user.getId());
        }
    }
    
  2. Kopieer en plak de volgende code aan het eind van de methode basicOperations.

    deleteUserDocument(maxaxam);
    
  3. Zorg dat u CosmosApp.java bouwt en uitvoert in de IDE of voer het programma uit in de terminal met behulp van:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    In de terminal wordt de volgende uitvoer weergegeven, waarbij 'Deleted user 1' aangeeft dat het document is verwijderd.

    INFO: Database and container validation complete
    INFO: User 1 already exists in the database
    INFO: User 2 already exists in the database
    INFO: Read User 1
    INFO: Replaced last name for Suh
    INFO: Deleted User 1
    

Programmatisch werken met documenten

Gegevens zijn opgeslagen in JSON-documenten in Azure Cosmos DB. Documenten in de portal kunnen programmatisch worden gemaakt, opgehaald, vervangen of verwijderd. Dit lab gaat over programmatische bewerkingen. Al deze bewerkingen zijn beschikbaar in azure Cosmos DB Java SDK en zijn ook toegankelijk via het Spring Data-programmeermodel. In deze module gebruiken we Spring Data Azure Cosmos DB om CRUD-bewerkingen (maken, ophalen, bijwerken en verwijderen) uit te voeren op NoSQL-gegevens die zijn opgeslagen in Azure Cosmos DB.

De belangrijkste bewerkingen voor Spring Data Azure Cosmos DB-documenten zijn basisbewerkingen in het Spring Data-programmeermodel:

  • save - een document punt-schrijven of bijwerken, afhankelijk van of het document al bestaat.
  • view - een document punt-lezen
  • delete - een document punt-verwijderen

Als u een van deze bewerkingen wilt uitvoeren, hebt u helperklassen (Java POJO-klassen) nodig die de objecten vertegenwoordigen die in de database zijn opgeslagen. Omdat we werken met een database met online klanten, kunt u het beste een WebCustomer-klasse gebruiken die gebruikersentiteiten vertegenwoordigt. Met deze klasse worden primaire gegevens opgeslagen, zoals voornaam, achternaam en gebruikers-ID. (De ID is vereist omdat dit de partitiesleutel is om horizontaal schalen mogelijk te maken.)

Omdat iedere webgebruiker enkele gekoppelde verzendvoorkeuren en coupons heeft, kunt u ShippingPreference- en CouponsUsed-gegevenstypen gebruiken om deze entiteiten weer te geven. Tot slot kan iedere webklant een bestelgeschiedenis hebben die mogelijk niet gebonden is. U kunt daarom het beste afzonderlijke OrderHistory-entiteiten met een bijbehorende Java POJO-klasse gebruiken.

Ga naar src/main/java/com/azure/cosmos/examples/springexamples. De WebCustomer-POJO wordt weergeven. Kijk nu in de map common. U ziet een aantal POJO's: ShippingPreference, OrderHistory en CouponsUsed. Daarom hebben we alle entiteits-POJO's en hun helperklassen verstrekt.

Vervolgens maken we een aantal entiteiten en voeren we enkele eenvoudige CRUD-bewerkingen uit op de Azure Cosmos DB-container en de daarin opgenomen documenten. U kunt Azure Cosmos DB een Jackson-ObjectNode-instantie doorgeven die rechtstreeks het JSON-document opgeeft. Maar Azure Cosmos DB kan ook Java-POJO's naar JSON serialiseren. Aangezien dit de eenvoudigste aanpak is en er verder geen verschillen zijn, raden we deze methode aan.

Documenten maken en bijwerken

  1. Open WebCustomer.java en bekijk de inhoud. Het ziet er ongeveer als volgt uit:

    // Copyright (c) Microsoft Corporation. All rights reserved.
    // Licensed under the MIT License.
    package com.azure.cosmos.examples.springexamples;
    
    import com.azure.cosmos.examples.springexamples.common.CouponsUsed;
    import com.azure.cosmos.examples.springexamples.common.OrderHistory;
    import com.azure.cosmos.examples.springexamples.common.ShippingPreference;
    import com.azure.spring.data.cosmos.core.mapping.Container;
    import com.azure.spring.data.cosmos.core.mapping.PartitionKey;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.List;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Container(containerName = "WebCustomer", ru = "400")
    public class WebCustomer {
    
        /** Document ID (required by Azure Cosmos DB). */
        private String id;
    
        /** WebCustomer ID. */
        private String userId;
    
        /** WebCustomer last name. */
        @PartitionKey
        private String lastName;
    
        /** WebCustomer first name. */
        private String firstName;
    
        /** WebCustomer email address. */
        private String email;
    
        /** WebCustomer dividend setting. */
        private String dividend;
    
        /** WebCustomer shipping preferences. */
        private ShippingPreference shippingPreference;
    
        /** WebCustomer order history. */
        private List<OrderHistory> orderHistory;
    
        /** Coupons recorded by the user. */
        private List<CouponsUsed> coupons;
    }
    

    Houd er rekening mee dat de toegangsmethoden voor de velden id, userId en andere velden impliciet zijn (dus niet gedefinieerd in code). Dit gedrag is mogelijk omdat we de annotatie Project Lombok @Data gebruiken om ze automatisch te maken.

    Met de annotatie @NoArgsConstructor wordt een constructor gegenereerd zonder argumenten voor het instellen van standaard veldwaarden. Met de annotatie @AllArgsConstructor wordt een andere constructor met een volledige set argumenten gegenereerd om alle veldwaarden rechtstreeks op te geven.

    Houd er rekening mee dat WebCustomer een id-eigenschap heeft. Alle Azure Cosmos DB-documenten vereisen een id-eigenschap en daarom moeten alle POJO's die we willen serialiseren naar JSON-documenten, een id-veld bevatten.

  2. Voeg de volgende methode toe aan CosmosSample.java:

    /**
     * Take in list of Java POJOs and insert them into the database.
     * @param webCustomers List of WebCustomer POJOs to insert.
     */
    private void createWebCustomerDocumentsIfNotExist(final List<WebCustomer> webCustomers) {
        Flux.fromIterable(webCustomers).flatMap(webCustomer -> {
            logger.info("Creating WebCustomer {}", webCustomer.getId());
            return this.reactiveWebCustomerRepository.save(webCustomer);
        }).blockLast();
    }
    
  3. Zoek de methode run en voeg de volgende code toe aan het einde van die methode.

    WebCustomer maxaxam = new WebCustomer(
            "1",
            "maxaxam",
            "Axam",
            "Max",
            "maxaxam@contoso.com",
            "2.0",
            new ShippingPreference(
                    1,
                    "90 W 8th St",
                    "",
                    "New York",
                    "NY",
                    "10001",
                    "USA"
            ),
            new ArrayList<OrderHistory>(Arrays.asList(
                    new OrderHistory(
                            "3",
                            "1000",
                            "08/17/2018",
                            "52.49"
                    )
            )),
            new ArrayList<CouponsUsed>(Arrays.asList(
                    new CouponsUsed(
                            "A7B89F"
                    )
            ))
    );
    
    WebCustomer nelapin = new WebCustomer(
            "2",
            "nelapin",
            "Pindakova",
            "Nela",
            "nelapin@contoso.com",
            "8.50",
            new ShippingPreference(
                    1,
                    "505 NW 5th St",
                    "",
                    "New York",
                    "NY",
                    "10001",
                    "USA"
            ),
            new ArrayList<OrderHistory>(Arrays.asList(
                    new OrderHistory(
                            "4",
                            "1001",
                            "08/17/2018",
                            "105.89"
                    )
            )),
            new ArrayList<CouponsUsed>(Arrays.asList(
                    new CouponsUsed(
                            "Fall 2018"
                    )
            ))
    );
    
    createWebCustomerDocumentsIfNotExist(new ArrayList(Arrays.asList(maxaxam, nelapin)));
    
  4. Bouw CosmosSample.java en voer die uit in de IDE, of voer het programma uit in de terminal met behulp van:

    mvn clean package
    mvn spring-boot:run
    

    In de uitvoer van de terminal ziet u

    INFO: Creating WebCustomer 1
    INFO: Creating WebCustomer 2
    

Gefeliciteerd U hebt uw eerste gegevens in Azure Cosmos DB gemaakt en/of bijgewerkt vanuit een Java-toepassing. Laat we eens evalueren wat u hier hebt gedaan.

Er zijn drie nieuwe acties in run:

  1. Maak of werk het WebCustomer-exemplaar van maxaxam bij.
  2. Maak of werk het WebCustomer-exemplaar van nelapin bij.
  3. Roep createWebCustomerDocumentsIfNotExist aan en geef maxaxam en nelapin door als een lijst.

Met het aanroepen van createWebCustomerDocumentsIfNotExist worden beide WebCustomer-instanties als items/documenten toegevoegd aan Azure Cosmos DB. Als u de WebCustomer-instanties doorgeeft als een lijst, is het onze bedoeling om een performante methode te modelleren om met behulp van een minimum aan rekenresources snel POJO's in Azure Cosmos DB op te nemen. createWebCustomerDocumentsIfNotExist implementeert efficiënte asynchrone invoeging van een lijst met POJO's. Als een van beide documenten al bestaat, wordt door save een update uitgevoerd in plaats van dat er een document wordt gemaakt.

Stel dat ons doel is om het aantal aanvragen per seconde per thread te maximaliseren. Ter vergelijking, de synchronisatiebenadering voor het schrijven van createWebCustomerDocumentsIfNotExist is om elk WebCustomer-exemplaar te herhalen in webCustomers. Voor elke WebCustomer webCustomer maken we een blokkerende aanroep naar save:

this.reactiveWebCustomerRepository.save(webCustomer).block(); // <= Note the .block() which loops until request response.

Deze synchronisatiestijl implementeert een intuïtief proces: aanvraag indienen, wachten op antwoord, volgende aanvraag indienen. createWebCustomerDocumentsIfNotExist gebruikt deze methode echter niet, omdat blokkerende aanroepen in feite CPU-cycli verspillen tijdens de reactietijd van de aanvraag, wat leidt tot een laag aantal aanvragen per seconde.

U kunt deze aanvragen/het tweede probleem omzeilen door meerdere threads te produceren om parallelle aanroepen voor het blokkeren van aanvragen te doen. De meerdere threads zorgen voor een betere uitvoering van de runtime. Maar als het uw doel is zuinig te zijn met threadresources, blijft dit een verspilling. Elke thread wordt opnieuw uitgevoerd tijdens de reactietijd van een aanvraag, terwijl de thread in plaats daarvan meerdere taken had kunnen verwerken voor iets anders, waardoor u per thread maar weinig aanvragen per seconde kunt sturen.

Daarom en omdat we u een threadefficiënte invoeging van Java POJO's willen tonen, hebben we in plaats daarvan een asynchroon voorbeeld van documentinvoeging gegeven. De ondersteuning voor Spring Data is afkomstig van Project Reactor, een Java-toepassingsframework dat een stroomgebaseerd programmeermodel met declaratieve gegevensstromen biedt voor asynchroon, gebeurtenisgestuurd programmeren. Met createWebCustomerDocumentsIfNotExist wordt de asynchrone programmering van Project Reactor geïmplementeerd.

In createWebCustomerDocumentsIfNotExist is Flux.fromIterable(webCustomers) een Project Reactor-factory-methode. Er wordt een Flux-exemplaar gemaakt dat een bron is van asynchrone gebeurtenissen. In dit geval bevat elke asynchrone gebeurtenis een argument van het WebCustomer-exemplaar. Het Flux-exemplaar bevat twee dergelijke gebeurtenissen, één voor maxaxam en één voor nelapin. De code in .flatMap( ... ).blockLast(); definieert een pijplijn van opeenvolgende bewerkingen die moeten worden uitgevoerd voor de gebeurtenissen die worden gegenereerd door het Flux-exemplaar.

In dit geval zijn de twee bewerkingen in de pijplijn save -aanroepen. Het idee is dat deze pijplijn bijna identiek is aan de synchrone implementatie, met dit verschil dat de save-aanroep niet blokkeren. Meer in het bijzonder betekent de aanroep van blockLast() een abonnement op de geassembleerde pijplijn, waardoor de Flux de twee eigen gebeurtenissen asynchroon uitvoert. Vervolgens wordt in de pijplijn binnen .flatMap( ... ).blockLast(); elk van deze gebeurtenissen op een pseudo-parallelle manier verwerkt. Wanneer een aanvraag is ingediend en er wordt gewacht op een reactie, verwerkt Project Reactor de andere aanvragen op de achtergrond, wat een essentiële factor is om het aantal aanvragen per seconde per thread te maximaliseren.

Nu we efficiënte asynchrone databaseaanvragen met Project Reactor hebben gedemonstreerd, worden er voor de rest van dit lab blokkerende asynchrone aanroepen (in principe sync-aanroepen) gebruikt om het proces eenvoudig te houden. Voor meer informatie over Project Reactor gaat u naar de handleiding voor Reactor-patronen van Azure Cosmos DB.

Documenten lezen

  1. Als u documenten uit de database wilt lezen, voegt u de volgende methode toe aan CosmosSample:

    /**
     * Take in a Java POJO argument, extract ID and partition key, and read the corresponding document from the container.
     * In this case the ID is the partition key.
     * @param webCustomer User POJO to pull ID and partition key from.
     */
    private WebCustomer readWebCustomerDocument(final WebCustomer webCustomer) {
        WebCustomer webCustomerResult = null;
    
        try {
            logger.info("Read webCustomer {}", webCustomer.getId());
            webCustomerResult = this.reactiveWebCustomerRepository.findById(webCustomer.getId(), new PartitionKey(webCustomer.getLastName())).block();
        } catch (CosmosException de) {
            logger.error("Failed to read webCustomer {}", webCustomer.getId(), de);
        }
    
        return webCustomer;
    }
    
  2. Kopieer en plak de volgende code aan het eind van de methode run, na de code voor het maken van het document:

    readWebCustomerDocument(maxaxam);
    
  3. Bouw CosmosSample.java en voer die uit in de IDE, of voer het programma uit in de terminal met behulp van:

    mvn clean package
    mvn spring-boot:run
    

    In de uitvoer van de terminal ziet u het volgende. 'Gebruiker 1 gelezen' geeft aan dat het document is opgehaald.

    INFO: Read webCustomer 1
    

Documenten verwijderen

  1. Kopieer en plak de deleteWebCustomerDocument-methode onder uw readWebCustomerDocument-methode.

    /**
     * Take in a Java POJO argument, extract ID and partition key,
     * and delete the corresponding document.
     * @param webCustomer User POJO representing the document update.
     */
    private void deleteWebCustomerDocument(final WebCustomer webCustomer) {
        try {
            this.reactiveWebCustomerRepository.deleteById(webCustomer.getId(),new PartitionKey(webCustomer.getLastName())).block();
            logger.info("Deleted webCustomer {}", webCustomer.getId());
        } catch (CosmosException de) {
            logger.error("User {} could not be deleted.", webCustomer.getId());
        }
    }
    
  2. Kopieer en plak de volgende code aan het eind van de methode run.

    deleteWebCustomerDocument(maxaxam);
    
  3. Bouw CosmosSample.java en voer die uit in de IDE, of voer het programma uit in de terminal met behulp van:

    mvn clean package
    mvn spring-boot:run
    

    In de uitvoer van de terminal ziet u het volgende. 'Gebruiker 1 verwijderd' geeft aan dat het document is verwijderd.

    INFO: Deleted webCustomer 1
    

In deze les hebt u documenten gemaakt, bijgewerkt, gelezen en verwijderd in uw Azure Cosmos DB-database.