

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 开始使用 DynamoDB 增强型客户端 API
<a name="ddb-en-client-getting-started"></a>

以下教程向您介绍了使用 DynamoDB 增强型客户端 API 所需的基础知识。

## 添加依赖项
<a name="ddb-en-client-gs-dep"></a>

要开始在项目中使用 DynamoDB 增强型客户端 API，请添加 Maven 构件 `dynamodb-enhanced` 的依赖项。如以下示例所示。

------
#### [ Maven ]

```
<project>
  <dependencyManagement>
   <dependencies>
      <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>bom</artifactId>
        <version><VERSION></version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
   </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>dynamodb-enhanced</artifactId>
    </dependency>
  </dependencies>
  ...
</project>
```

在 Maven 中央存储库中搜索[最新版本](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)并*<VERSION>*替换为该值。

------
#### [ Gradle ]

```
repositories {
    mavenCentral()
}
dependencies {
    implementation(platform("software.amazon.awssdk:bom:<VERSION>"))
    implementation("software.amazon.awssdk:dynamodb-enhanced")
    ...
}
```

在 Maven 中央存储库中搜索[最新版本](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)并*<VERSION>*替换为该值。

------

# 从数据类生成 `TableSchema`
<a name="ddb-en-client-gs-tableschema"></a>

`[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)` 使增强型客户端能够将 DynamoDB 属性值映射到您的客户端类，反之亦然。在本教程中，您将了解两类 `TableSchema`，一类是从静态数据类派生的，另一类是使用生成器从代码中生成的。

## 使用带注释的数据类
<a name="ddb-en-client-gs-tableschema-anno-bean"></a>

适用于 Java 的 SDK 2.x 包含[一组注释](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html)，您可以将其与数据类结合使用，以快速生成 `TableSchema` 来将类映射到表。

首先创建一个符合[JavaBean 规范](https://download.oracle.com/otn-pub/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/beans.101.pdf)的数据类。该规范要求类具有无参数的公共构造函数，并且类中的每个属性都有 getter 和 setter。包括类级别的注释，以指示数据类是 `DynamoDbBean`. 此外，至少要在 getter 或 setter 上包含关于主键属性的 `DynamoDbPartitionKey` 注释。

您可以对 getter 或 setter 应用[属性级注释](ddb-en-client-anno-index.md)，但不能同时应用两者。

**注意**  
该术语`property`通常用于封装在 a 中的值。 JavaBean但是，为了与 DynamoDB 使用的术语保持一致，本指南（英文版）改用术语 `attribute`。（中文版中，两者的翻译均为“属性”。）

以下 `Customer` 类展示了将类定义链接到 DynamoDB 表的注释。

### `Customer` 类
<a name="ddb-en-client-gs-tableschema-anno-bean-cust"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.time.Instant;

@DynamoDbBean
public class Customer {

    private String id;
    private String name;
    private String email;
    private Instant regDate;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }

    public void setId(String id) { this.id = id; }

    public String getCustName() { return this.name; }

    public void setCustName(String name) { this.name = name; }

    @DynamoDbSortKey
    public String getEmail() { return this.email; }

    public void setEmail(String email) { this.email = email; }

    public Instant getRegistrationDate() { return this.regDate; }

    public void setRegistrationDate(Instant registrationDate) { this.regDate = registrationDate; }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", email=" + email
                + ", regDate=" + regDate + "]";
    }
}
```

创建带注释的数据类后，使用它来创建 `TableSchema`，如以下代码段所示。

```
static final TableSchema<Customer> customerTableSchema = TableSchema.fromBean(Customer.class);
```

`TableSchema` 被设计为静态且不可变。您通常可以在类加载时将其实例化。

静态 `TableSchema.fromBean()` 工厂方法对 bean 进行自检，生成数据类属性与 DynamoDB 属性之间的映射。

有关使用由多个数据类组成的数据模型的示例，请参阅[处理属性值为 bean、map、list 和 set 的对象](ddb-en-client-adv-features-nested.md)部分中的 `Person` 类。

## 使用生成器
<a name="ddb-en-client-gs-tableschema-builder"></a>

如果您在代码中定义表架构，则可以避免 Bean 自检的开销。如果您对架构进行编码，则您的类无需遵循 JavaBean 命名标准，也不需要对其进行注释。以下示例使用生成器，与使用注释的 `Customer` 类示例等效。

```
static final TableSchema<Customer> customerTableSchema =
                TableSchema.builder(Customer.class)
                        .newItemSupplier(Customer::new)
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(Customer::getId)
                                .setter(Customer::setId)
                                .tags(StaticAttributeTags.primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("email")
                                .getter(Customer::getEmail)
                                .setter(Customer::setEmail)
                                .tags(StaticAttributeTags.primarySortKey()))
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(Customer::getCustName)
                                .setter(Customer::setCustName))
                        .addAttribute(Instant.class, a -> a.name("registrationDate")
                                .getter(Customer::getRegistrationDate)
                                .setter(Customer::setRegistrationDate))
                        .build();
```

# 创建增强型客户端和 `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable"></a>

## 创建增强型客户端
<a name="ddb-en-client-getting-started-dynamodbTable-eclient"></a>

该[DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)类或其异步类是使用 DynamoDB 增强型客户端 API 的入口点。[DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html)

增强型客户端需要标准 `[DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)` 才能执行工作。API 提供了两种创建 `DynamoDbEnhancedClient` 实例的方法。第一个选项是使用从配置设置中选取的默认设置创建标准 `DynamoDbClient`，如以下代码段所示。

```
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create();
```

如果要配置底层标准客户端，可以将其提供给增强型客户端的生成器方法，如以下代码段所示。

```
// Configure an instance of the standard DynamoDbClient.
DynamoDbClient standardClient = DynamoDbClient.builder()
    .region(Region.US_EAST_1)
    .credentialsProvider(ProfileCredentialsProvider.create())
    .build();

// Use the configured standard client with the enhanced client.
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
    .dynamoDbClient(standardClient)
    .build();
```

## 创建 `DynamoDbTable` 实例
<a name="ddb-en-client-getting-started-dynamodbTable-table"></a>

可以将 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html) 视为使用 `TableSchema` 提供的映射功能的 DynamoDB 表的客户端表示形式。该 `DynamoDbTable` 类提供了 CRUD 操作的方法，允许您与单个 DynamoDB 表进行交互。

`DynamoDbTable<T>` 是一个采用单一类型参数的通用类，无论是自定义类还是处理文档类型项目时的 `EnhancedDocument`。此参数类型在您使用的类和单个 DynamoDB 表之间建立关系。

使用 `DynamoDbEnhancedClient` 的 `table()` 工厂方法创建 `DynamoDbTable` 实例，如以下代码段所示。

```
static final DynamoDbTable<Customer> customerTable = 
        enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

`DynamoDbTable` 实例是单例类的候选实例，因为它们是不可变的，可以在整个应用程序中使用。

现在，您的代码具有可以使用 `Customer` 实例的 DynamoDB 表内存表示形式。实际的 DynamoDB 表可能存在，也可能不存在。如果名为 `Customer` 的表已经存在，则可以开始对其执行 CRUD 操作。如果该表不存在，请使用 `DynamoDbTable` 实例创建表，如下一部分所述。

# 如果需要，创建 DynamoDB 表
<a name="ddb-en-client-gs-ddbtable"></a>

创建 `DynamoDbTable` 实例后，使用它在 DynamoDB 中*一次性* 创建表。

## 创建表示例代码
<a name="ddb-en-client-gs-ddbtable-createex"></a>

以下示例基于 `Customer` 数据类创建一个 DynamoDB 表。

此示例创建了一个 DynamoDB 表，其名称为 `Customer`（与类名称相同，但表名称可以是其他名称）。不管您如何为表命名，都必须在其他应用程序中使用该名称才能使用该表。为了使用底层 DynamoDB 表，每次创建另一个 `DynamoDbTable` 对象时，都要为 `table()` 方法提供此名称。

传递给 `createTable` 方法的 Java lambda 参数 `builder` 允许您[自定义表](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html)。在此示例中，配置了[预置吞吐量](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual)。要在创建表时使用默认设置，请跳过生成器，如以下代码段所示。

```
customerTable.createTable();
```

使用默认设置时，不会设置预置吞吐量的值。取而代之的是，表的计费模式将设置为[按需](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand)。

该示例还在尝试打印出响应中收到的表名称之前使用了 `[DynamoDbWaiter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/waiters/DynamoDbWaiter.html)`。创建表需要一些时间。因此，使用 waiter 意味着您不必编写在使用表之前轮询 DynamoDB 服务，以查看表是否存在的逻辑。

### 导入
<a name="ddb-en-client-gs-ddbtable-imports"></a>

```
import com.example.dynamodb.Customer;
import software.amazon.awssdk.core.internal.waiters.ResponseOrException;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
```

### 代码
<a name="ddb-en-client-gs-ddbtable-code"></a>

```
 public static void createCustomerTable(DynamoDbTable<Customer> customerTable, DynamoDbClient standardClient) {
     // Create the DynamoDB table using the 'customerTable' DynamoDbTable instance.
     customerTable.createTable(builder -> builder
             .provisionedThroughput(b -> b
                     .readCapacityUnits(10L)
                     .writeCapacityUnits(10L)
                     .build())
     );
     // The DynamoDbClient instance (named 'standardClient') passed to the builder for the DynamoDbWaiter is the same instance
     // that was passed to the builder of the DynamoDbEnhancedClient instance that we created previously.
     // By using the same instance, it ensures that the same Region that was configured on the standard DynamoDbClient 
     // instance is used for other service clients that accept a DynamoDbClient during construction.
     try (DynamoDbWaiter waiter = DynamoDbWaiter.builder().client(standardClient).build()) { // DynamoDbWaiter is Autocloseable
         ResponseOrException<DescribeTableResponse> response = waiter
                 .waitUntilTableExists(builder -> builder.tableName("Customer").build())
                 .matched();
         DescribeTableResponse tableDescription = response.response().orElseThrow(
                 () -> new RuntimeException("Customer table was not created."));
         // The actual error can be inspected in response.exception()
         logger.info("Customer table was created.");
     }
 }
```

**注意**  
从数据类生成表时，DynamoDB 表的属性名称以小写字母开头。如果您希望表的属性名称以大写字母开头，请使用 [`@DynamoDbAttribute(NAME)` 注释](ddb-en-client-adv-features-inex-attr.md)并提供所需的名称作为参数。

# 执行操作
<a name="ddb-en-client-gs-use"></a>

创建表后，请使用 `DynamoDbTable` 实例对 DynamoDB 表执行操作。

在以下示例中，将单例 `DynamoDbTable<Customer>` 作为参数与 [`Customer` 数据类](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust)实例一起传递，以向表中添加新项目。

```
    public static void putItemExample(DynamoDbTable<Customer> customerTable, Customer customer){
        logger.info(customer.toString());
        customerTable.putItem(customer);
    }
```

## `Customer` 对象
<a name="perform_ops_create_customer_instatnce"></a>

```
        Customer customer = new Customer();
        customer.setId("1");
        customer.setCustName("Customer Name");
        customer.setEmail("customer@example.com");
        customer.setRegistrationDate(Instant.parse("2023-07-03T10:15:30.00Z"));
```

在将 `customer` 对象发送到 DynamoDB 服务之前，请记录对象的 `toString()` 方法的输出，以将其与增强型客户端发送的内容进行比较。

```
Customer [id=1, name=Customer Name, email=customer@example.com, regDate=2023-07-03T10:15:30Z]
```

线级日志记录显示生成的请求的有效负载。增强型客户端从数据类生成了低级别表示形式。`regDate` 属性是 Java 中的一种 `Instant` 类型，以 DynamoDB 字符串的形式表示。

```
{
  "TableName": "Customer",
  "Item": {
    "registrationDate": {
      "S": "2023-07-03T10:15:30Z"
    },
    "id": {
      "S": "1"
    },
    "custName": {
      "S": "Customer Name"
    },
    "email": {
      "S": "customer@example.com"
    }
  }
}
```

# 使用现有表
<a name="ddb-en-client-gs-existingtable"></a>

上一部分介绍了如何从 Java 数据类开始，创建 DynamoDB 表。如果您已有表，并且想要使用增强型客户端的功能，则可以创建一个 Java 数据类来使用该表。您需要检查 DynamoDB 表并为数据类添加必要的注释。

在使用现有表之前，请调用 `DynamoDbEnhanced.table()` 方法。在前面的示例中，这是通过以下语句完成的。

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

返回 `DynamoDbTable` 实例后，您可以立即开始使用底层表。您无需通过调用 `DynamoDbTable.createTable()` 方法来重新创建表。

以下示例通过立即从 DynamoDB 表中检索 `Customer` 实例，演示了这一点。

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
// The Customer table exists already and has an item with a primary key value of "1" and a sort key value of "customer@example.com".
customerTable.getItem(
        Key.builder().
                partitionValue("1").
                sortValue("customer@example.com").build());
```

**重要**  
`table()` 方法中使用的表名称必须与现有 DynamoDB 表名称相匹配。