练习 - 以编程方式创建、读取、更新和删除 NoSQL 数据

已完成

已建立与 Azure Cosmos DB 的连接。 在本单元中,你将在你的 WebCustomers 集合中创建用户文档。 然后,将按 ID 对文档进行检索、替换和删除。

以编程方式处理文档

数据存储在 Azure Cosmos DB 内的 JSON 文档中。 可在门户中或以编程方式创建、检索、替换或删除文档。 本实验室重点介绍编程操作。 Azure Cosmos DB 提供适合 .NET、.NET Core、Java、Node.js 和 Python 的客户端 SDK,其中每种语言都支持这些操作。 本模块将使用 Java SDK 对存储在 Azure Cosmos DB 中的 NoSQL 数据执行 CRUD(创建、检索、更新和删除)操作。

用于 Azure Cosmos DB 文档的主要操作是 CosmosAsyncContainer 类的一部分:

Upsert 执行创建或替换操作,具体取决于文档是否已经存在。

若要执行上述任一操作,需要表示在数据库中存储的对象的帮助程序类(Java POJO 类)。 我们使用的是用户的数据库,因此你需要一个表示用户实体的 User 类。 此类将存储主数据,如名字、姓氏和用户 ID。 (ID 是必需的,因为这是用于启用水平缩放的分区键。)

每个用户都有一些关联的发货首选项和优惠券,因此你需要使用 ShippingPreferenceCouponsUsed 数据类型来表示这些实体。 最后,每位用户或许会有一些可能未绑定的订单历史记录,因此需要具有带相应 Java POJO 类的单独的 OrderHistory 实体。

转到 src/main/java/com/azure/azure-cosmos-java-sql-app-mslearn 并查看“datatypes”文件夹。 你将看到多个 POJO:UserShippingPreferenceOrderHistoryCouponsUsed。 因此,我们提供了所有实体 POJO 及其帮助程序类!

接下来,我们将创建一些实体,并对 Azure Cosmos DB 容器及其包含的文档执行一些基本的 CRUD 操作。 你可以向 Azure Cosmos DB 传递一个直接指定 JSON 文档的 Jackson ObjectNode 实例。 但是 Azure Cosmos DB 也可以将 Java POJO 序列化为 JSON,因此我们建议使用此最简单的方法(所有其他条件都相等)。

创建文档

  1. 打开 User.java,并检查其内容。 结果应如下所示:

    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;
    }
    

    观察到 iduserId 和其他字段的访问方法是隐式的(未在代码中定义)。 因为我们使用 Project Lombok @Data 注释来自动创建,所以可能会出现此行为。

    @NoArgsConstructor 注释将生成一个构造函数,它没有用于设置默认字段值的参数。 @AllArgsConstructor 注释将使用一组完整的参数生成另一个构造函数,以直接指定所有字段值。

    请注意,User 具有 id 属性。 所有 Azure Cosmos DB 文档都需要 id 属性,因此我们打算序列化为 JSON 文档的所有 POJO 都必须具有 id 字段。

  2. 将以下方法添加到 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. 返回到 basicOperations 方法,并在 client.close() 调用之前将以下内容添加到该方法末尾。

    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. 在 IDE 中生成并运行 CosmosApp.java,或使用以下内容在终端中运行程序:

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

    当应用程序创建每个新的用户文档时,终端会显示输出。

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

    你可能还会看到记录器发出的一些其他文本,如 timestamps。

祝贺你! 你已通过 Java 应用程序在 Azure Cosmos DB 中创建了你的第一个数据。 让我们稍作暂停,评估一下你在此处执行的操作。

basicOperations 中有三个新操作:

  1. 创建 maxaxam User 实例。
  2. 创建 nelapin User 实例。
  3. 调用 createUserDocumentsIfNotExist,并在列表中传入 maxaxam 和 nelapin。

调用 createUserDocumentsIfNotExist 会插入这两个 User 实例作为 Azure Cosmos DB 中的项/文档。 在将 User 实例作为列表传递后,我们的目的是使用最少的计算资源将引入 POJO 的高性能方法快速建模到 Azure Cosmos DB 中。 createUserDocumentsIfNotExist 可实现 POJO 列表的高效异步插入。

假设我们的目标是将每个线程的每秒请求数最大化。 为了进行比较,写入 createUserDocumentsIfNotExist 的同步方法(暂时忽略 readItem 检查)将在 users 中循环访问每个 User 实例。 对于每个 User u,将对 createItem 执行阻塞调用

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

此同步样式实现了直观的进程:发出请求、等待响应、发出下一个请求。 但是,createUserDocumentsIfNotExist 不使用这种方法,因为阻塞调用会在请求响应时间浪费 CPU 周期,导致每秒的请求数较低。

你可通过生成多个线程来执行并行阻塞请求调用,解决每秒请求数的问题。 多线程会缩短执行时间。 但如果你的目标是节省线程资源,那么这样做仍会浪费资源。 在请求响应时间内,每个线程都会循环,而这时它可以按多任务方式执行其他操作,使每个线程的每秒请求数很低。

因此,为了展示 Java POJO 的线程高效插入,我们改为提供异步文档插入示例。 Azure Cosmos DB Java SDK v4 异步支持来自项目反应器,这是一个 Java 应用程序框架,为事件驱动的异步编程提供基于流的声明性数据流编程模型。 createDocumentsIfNotExist 可实现项目反应器异步编程。

createUserDocumentsIfNotExist 中,Flux.fromIterable(users) 是项目反映器工厂方法。 它创建一个 Flux 实例作为异步事件的源。 在这种情况下,每个异步“事件”都包含一个 User 实例参数。 Flux 实例包含两个这样的事件,一个用于 maxaxam,一个用于 nelapin。 .flatMap( ... ).blockLast(); 中的代码定义了对 Flux 实例发出的事件执行的顺序操作管道。

其中一项操作是 createItem。 我们的想法是,除了我们不对 createItem 调用进行阻塞外,这个管道与同步实现几乎相同。 具体来说,调用 blockLast() 将订阅已组装的管道,导致 Flux 异步发出其两个事件。 然后,.flatMap( ... ).blockLast(); 中的管道以伪并行方式处理每个事件。 发出一个请求并等待响应时,项目反应器将在后台处理其他请求,这是最大化每个线程每秒请求数的关键因素。

至此,我们演示了如何使用项目反应器实现高效的异步数据库请求;为简单起见,本实验室的其余部分将使用阻塞(同步)调用。 若要详细了解项目反应器,请参阅 Azure Cosmos DB 反应器模式指南

读取文档

  1. 若要读取数据库中的文档,请将以下方法添加到 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. 在文档创建代码之后,将以下代码复制粘贴到 basicOperations 方法末尾:

    readUserDocument(maxaxam);
    
  3. 在 IDE 中生成并运行 CosmosApp.java,或使用以下内容在终端中运行程序:

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

    终端显示如下输出,其中“Read user 1”指明已检索到文档。

    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
    

    你可能还会看到记录器发出的其他文本。

替换文档

Azure Cosmos DB 支持替换 JSON 文档。 此示例将把用户记录更新为反映用户姓氏更改。

  1. 在 CosmosApp.java 文件中的 readUserDocument 方法后面添加 replaceUserDocument 方法。

    /**
     * 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. 在文档读取代码之后,将以下代码复制粘贴到 basicOperations 方法末尾。

    maxaxam.setLastName("Suh");
    replaceUserDocument(maxaxam);
    
  3. 在 IDE 中生成并运行 CosmosApp.java,或使用以下内容在终端中运行程序:

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

    终端显示以下输出,其中“Replaced last name for Suh”指明已替换文档。

    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
    

删除文档

  1. deleteUserDocument 方法复制粘贴到 replaceUserDocument 方法下。

    /**
     * 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. 复制以下代码并将其粘贴到 basicOperations 方法末尾。

    deleteUserDocument(maxaxam);
    
  3. 在 IDE 中生成并运行 CosmosApp.java,或使用以下内容在终端中运行程序:

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

    终端会显示如下输出,其中“Deleted user 1”表示已删除该文档。

    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
    

以编程方式处理文档

数据存储在 Azure Cosmos DB 内的 JSON 文档中。 可在门户中或以编程方式创建、检索、替换或删除文档。 本实验室重点介绍编程操作。 所有这些操作都在 Azure Cosmos DB Java SDK 中提供,也可以通过 Spring Data 编程模型进行访问。 本模块将使用 Spring Data Azure Cosmos DB 对存储在 Azure Cosmos DB 中的 NoSQL 数据执行 CRUD(创建、检索、更新和删除)操作。

Spring Data Azure Cosmos DB 文档的主要操作是 Spring Data 编程模型中的基本操作:

  • save - 点-编写或更新文档,具体取决于文档是否已存在。
  • view - 点-读取文档
  • delete - 点-删除文档

若要执行上述任一操作,需要表示在数据库中存储的对象的帮助程序类(Java POJO 类)。 我们使用的是在线客户的数据库,因此你需要使用表示用户实体的 WebCustomer 类。 此类将存储主数据,如名字、姓氏和用户 ID。 (ID 是必需的,因为这是用于启用水平缩放的分区键。)

每个 Web 客户都有一些关联的发货首选项和优惠券,因此你需要使用 ShippingPreferenceCouponsUsed 数据类型来表示这些实体。 最后,每个 Web 客户或许会有一些可能未绑定的订单历史记录,因此需要具有带相应 Java POJO 类的单独的 OrderHistory 实体。

转到 src/main/java/com/azure/cosmos/examples/springexamples。 你将会看到 WebCustomer POJO。 现在,查看 common 文件夹。 你将看到多个 POJO:ShippingPreferenceOrderHistoryCouponsUsed。 因此,我们提供了所有实体 POJO 及其帮助程序类!

接下来,我们将创建一些实体,并对 Azure Cosmos DB 容器及其包含的文档执行一些基本的 CRUD 操作。 你可以向 Azure Cosmos DB 传递一个直接指定 JSON 文档的 Jackson ObjectNode 实例。 但是 Azure Cosmos DB 也可以将 Java POJO 序列化为 JSON,因此我们建议使用此最简单的方法(所有其他条件都相等)。

创建和更新文档

  1. 打开 WebCustomer.java,并检查其内容。 结果应如下所示:

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

    观察到 iduserId 和其他字段的访问方法是隐式的(未在代码中定义)。 因为我们使用 Project Lombok @Data 注释来自动创建,所以可能会出现此行为。

    @NoArgsConstructor 注释将生成一个构造函数,它没有用于设置默认字段值的参数。 @AllArgsConstructor 注释将使用一组完整的参数生成另一个构造函数,以直接指定所有字段值。

    请注意,WebCustomer 具有 id 属性。 所有 Azure Cosmos DB 文档都需要 id 属性,因此我们打算序列化为 JSON 文档的所有 POJO 都必须具有 id 字段。

  2. 将以下方法添加到 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. 找到 run 方法,并将以下代码添加到该方法的末尾。

    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. 在 IDE 中生成并运行 CosmosSample.java,或使用以下内容在终端中运行程序:

    mvn clean package
    mvn spring-boot:run
    

    在终端输出中,你应看到

    INFO: Creating WebCustomer 1
    INFO: Creating WebCustomer 2
    

祝贺! 你已通过 Java 应用程序在 Azure Cosmos DB 中创建和/或更新了你的第一个数据。 让我们稍作暂停,评估一下你在此处执行的操作。

run 中有三个新操作:

  1. 创建/更新 maxaxam WebCustomer 实例。
  2. 创建/更新 nelapin WebCustomer 实例。
  3. 调用 createWebCustomerDocumentsIfNotExist,并在列表中传入 maxaxam 和 nelapin。

调用 createWebCustomerDocumentsIfNotExist 会插入这两个 WebCustomer 实例作为 Azure Cosmos DB 中的项/文档。 在将 WebCustomer 实例作为列表传递后,我们的目的是使用最少的计算资源将引入 POJO 的高性能方法快速建模到 Azure Cosmos DB 中。 createWebCustomerDocumentsIfNotExist 可实现 POJO 列表的高效异步插入。 如果任何一个文档已存在,则 save 将完成更新而不是创建文档。

假设我们的目标是将每个线程的每秒请求数最大化。 为了进行比较,写入 createWebCustomerDocumentsIfNotExist 的同步方法将循环访问 webCustomers 中的每个 WebCustomer 实例。 对于每个 WebCustomer webCustomer,将对 save 执行阻塞调用

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

此同步样式实现了直观的进程:发出请求、等待响应、发出下一个请求。 但是,createWebCustomerDocumentsIfNotExist 不使用这种方法,因为阻塞调用会在请求响应时间浪费 CPU 周期,导致每秒的请求数较低。

你可通过生成多个线程来执行并行阻塞请求调用,解决每秒请求数的问题。 多线程会缩短执行时间。 但如果你的目标是节省线程资源,那么这样做仍会浪费资源。 在请求响应时间内,每个线程都会循环,而这时它可以按多任务方式执行其他操作,使每个线程的每秒请求数很低。

因此,为了展示 Java POJO 的线程高效插入,我们改为提供异步文档插入示例。 Spring Data 异步支持来自项目反应器,这是一个 Java 应用程序框架,为事件驱动的异步编程提供基于流的声明性数据流编程模型。 createWebCustomerDocumentsIfNotExist 可实现项目反应器异步编程。

createWebCustomerDocumentsIfNotExist 中,Flux.fromIterable(webCustomers) 是项目反映器工厂方法。 它创建一个 Flux 实例作为异步事件的源。 在这种情况下,每个异步“事件”都包含一个 WebCustomer 实例参数。 Flux 实例包含两个这样的事件,一个用于 maxaxam,一个用于 nelapin。 .flatMap( ... ).blockLast(); 中的代码定义了对 Flux 实例发出的事件执行的顺序操作管道。

在这种情况下,管道中的两个操作都是 save 调用。 我们的想法是,除了我们不对 save 调用进行阻塞外,这个管道与同步实现几乎相同。 具体来说,调用 blockLast() 将订阅已组装的管道,导致 Flux 异步发出其两个事件。 然后,.flatMap( ... ).blockLast(); 中的管道以伪并行方式处理每个事件。 发出一个请求并等待响应时,项目反应器将在后台处理其他请求,这是最大化每个线程每秒请求数的关键因素。

至此,我们演示了如何使用项目反应器实现高效的异步数据库请求;为简单起见,本实验室的其余部分将使用阻塞异步调用(有效的同步调用)。 若要详细了解项目反应器,请参阅 Azure Cosmos DB 反应器模式指南

读取文档

  1. 若要读取数据库中的文档,请将以下方法添加到 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. 在文档创建代码之后,将以下代码复制粘贴到 run 方法末尾:

    readWebCustomerDocument(maxaxam);
    
  3. 在 IDE 中生成并运行 CosmosSample.java,或使用以下内容在终端中运行程序:

    mvn clean package
    mvn spring-boot:run
    

    在终端输出中,你应看到以下内容。 “读取用户 1”指示已检索到文档。

    INFO: Read webCustomer 1
    

删除文档

  1. deleteWebCustomerDocument 方法复制粘贴到 readWebCustomerDocument 方法下。

    /**
     * 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. 复制以下代码并将其粘贴到 run 方法末尾。

    deleteWebCustomerDocument(maxaxam);
    
  3. 在 IDE 中生成并运行 CosmosSample.java,或使用以下内容在终端中运行程序:

    mvn clean package
    mvn spring-boot:run
    

    在终端输出中,你应看到以下内容。 “已删除用户 1”指示文档已被删除。

    INFO: Deleted webCustomer 1
    

在本单元中,你在 Azure Cosmos DB 数据库中创建、更新、读取及删除了文档。