

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

# 适用于 Java 的 SDK 版本 1 和版本 2 之间的 DynamoDB APIs 映射发生了变化
<a name="dynamodb-mapping-api-changes"></a>

## 创建客户端
<a name="dynamodb-mapping-api-changes-client"></a>


****  

| 使用案例 | V1 | V2 | 
| --- | --- | --- | 
|   正常实例化  |  <pre>AmazonDynamoDB standardClient = AmazonDynamoDBClientBuilder.standard()<br />    .withCredentials(credentialsProvider)<br />    .withRegion(Regions.US_EAST_1)<br />    .build();<br />DynamoDBMapper mapper = new DynamoDBMapper(standardClient);</pre>  |  <pre>DynamoDbClient standardClient = DynamoDbClient.builder()<br />    .credentialsProvider(ProfileCredentialsProvider.create())<br />    .region(Region.US_EAST_1)<br />    .build();<br />DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()<br />    .dynamoDbClient(standardClient)<br />    .build();</pre>  | 
|   最小实例化  |  <pre>AmazonDynamoDB standardClient = AmazonDynamoDBClientBuilder.standard();<br />DynamoDBMapper mapper = new DynamoDBMapper(standardClient);</pre>  |  <pre>DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create();</pre>  | 
|   带属性转换器\$1  |  <pre>DynamoDBMapper mapper = new DynamoDBMapper(standardClient, <br />                        attributeTransformerInstance);</pre>  |  <pre>DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()<br />    .dynamoDbClient(standardClient)<br />    .extensions(extensionAInstance, extensionBInstance)<br />    .build();</pre>  | 

\$1V2 中的扩展与 V1 中的属性转换器大致对应。[使用扩展自定义 DynamoDB 增强型客户端操作](ddb-en-client-extensions.md) 部分包含有关 V2 中扩展的更多信息。

## 建立到 DynamoDB 表/索引的映射
<a name="dynamodb-mapping-api-changes-mapping"></a>

在 V1 中，通过 bean 注释指定 DynamoDB 表名。在 V2 中，使用一种工厂方法 `table()` 来生成代表远程 DynamoDB 表的 `DynamoDbTable` 实例。`table()` 方法的第一个参数是 DynamoDB 表名。


****  

| 使用案例 | V1 | V2 | 
| --- | --- | --- | 
|   将 Java POJO 类映射到 DynamoDB 表  |  <pre>@DynamoDBTable(tableName ="Customer")<br />public class Customer {<br />  ...<br />}</pre>  |  <pre>DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer",<br />    TableSchema.fromBean(Customer.class));</pre>  | 
|   映射到 DynamoDB 二级索引  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html) 《DynamoDB 开发人员指南》中讨论 [V1 `query` 方法](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html#DynamoDBMapper.Methods.query)的部分展示了一个完整的示例。  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html) 本指南中的 [使用二级索引](ddb-en-client-use-secindex.md) 部分提供了更多信息。  | 

## 表操作
<a name="dynamodb-mapping-api-changes-tobleops"></a>

本节介绍大多数标准用例中 V1 和 V2 之间存在差异的操作 APIs 。

在 V2 中，所有涉及单个表的操作都是在 `DynamoDbTable` 实例上调用，而不是在增强型客户端上调用。增强型客户端包含可以针对多个表的方法。

在下面名为*表操作*的表中，POJO 实例被称为 `item` 或称为某个具体类型（例如 `customer1`）。对于 V2 示例，名为 `table` 的实例是先前调用 `enhancedClient.table()` 的结果，该调用返回对 `DynamoDbTable` 实例的引用。

请注意，即使未显示，也可以使用 fluent 使用者模式调用大多数 V2 操作。例如，

```
Customer customer = table.getItem(r → r.key(key));
  or
Customer customer = table.getItem(r → r.key(k -> k.partitionValue("id").sortValue("email")))
```

对于 V1 操作，*表操作*（在下方）包含一些常用的表单，并未涵盖所有重载表单。例如，`load()` 方法有以下重载：

```
mapper.load(Customer.class, hashKey)
mapper.load(Customer.class, hashKey, rangeKey)
mapper.load(Customer.class, hashKey, config)
mapper.load(Customer.class, hashKey, rangeKey, config)
mapper.load(item)
mapper.load(item, config)
```

*表操作*（在下方）显示了常用的表单：

```
mapper.load(item)
mapper.load(item, config)
```


**表操作**  

| 使用案例 | V1 | V2 | 
| --- | --- | --- | 
|  将 Java POJO 写入 DynamoDB 表 **DynamoDB 操作**：`PutItem`，`UpdateItem`  |  <pre>mapper.save(item)<br />mapper.save(item, config)<br />mapper.save(item, saveExpression, config)</pre> 在 V1 中，`DynamoDBMapperConfig.SaveBehavior` 和注释决定了将调用哪个低级 DynamoDB 方法。通常，除非在使用 `SaveBehavior.CLOBBER` 和 `SaveBehavior.PUT`，否则会调用 `UpdateItem`。自动生成的密钥是一种特殊的使用案例，偶尔会同时使用 `PutItem` 和 `UpdateItem`。  |  <pre>table.putItem(putItemRequest)<br />table.putItem(item)<br />table.putItemWithResponse(item) //Returns metadata.<br /><br />updateItem(updateItemRequest)<br />table.updateItem(item)<br />table.updateItemWithResponse(item) //Returns metadata.</pre>  | 
|  从 DynamoDB 表中将项目读取到 Java POJO **DynamoDB 操作：**`GetItem`  |  <pre>mapper.load(item)<br />mapper.load(item, config)</pre>  |  <pre>table.getItem(getItemRequest)<br />table.getItem(item)<br />table.getItem(key)<br />table.getItemWithResponse(key) //Returns POJO with metadata.</pre>  | 
|  从 DynamoDB 表中删除项目 **DynamoDB 操作：**`DeleteItem`  |  <pre>mapper.delete(item, deleteExpression, config)</pre>  |  <pre>table.deleteItem(deleteItemRequest)<br />table.deleteItem(item)<br />table.deleteItem(key)</pre>  | 
|  查询 DynamoDB 表或二级索引并返回分页列表 **DynamoDB 操作：**`Query`  |  <pre>mapper.query(Customer.class, queryExpression)<br />mapper.query(Customer.class, queryExpression, <br />                             mapperConfig)</pre>  |  <pre>table.query(queryRequest)<br />table.query(queryConditional)</pre> 使用返回的 `PageIterable.stream()`（延迟加载）进行同步响应，使用 `PagePublisher.subscribe()` 进行异步响应  | 
|  查询 DynamoDB 表或二级索引并返回列表 **DynamoDB 操作：**`Query`  |  <pre>mapper.queryPage(Customer.class, queryExpression)<br />mapper.queryPage(Customer.class, queryExpression, <br />                                 mapperConfig)</pre>  |  <pre>table.query(queryRequest)<br />table.query(queryConditional)</pre> 使用返回的 `PageIterable.items()`（延迟加载）进行同步响应，使用 `PagePublisher.items.subscribe()` 进行异步响应  | 
|  扫描 DynamoDB 表或二级索引并返回分页列表 **DynamoDB 操作：**`Scan`  |  <pre>mapper.scan(Customer.class, scanExpression)<br />mapper.scan(Customer.class, scanExpression, <br />                            mapperConfig)</pre>  |  <pre>table.scan()<br />table.scan(scanRequest)</pre> 使用返回的 `PageIterable.stream()`（延迟加载）进行同步响应，使用 `PagePublisher.subscribe()` 进行异步响应  | 
|  扫描 DynamoDB 表或二级索引并返回列表 **DynamoDB 操作：**`Scan`  |  <pre>mapper.scanPage(Customer.class, scanExpression)<br />mapper.scanPage(Customer.class, scanExpression, <br />                                mapperConfig)</pre>  |  <pre>table.scan()<br />table.scan(scanRequest)</pre> 使用返回的 `PageIterable.items()`（延迟加载）进行同步响应，使用 `PagePublisher.items.subscribe()` 进行异步响应  | 
|  批量读取多个表中的多个项目 **DynamoDB 操作：**`BatchGetItem`  |  <pre>mapper.batchLoad(Arrays.asList(customer1, <br />                               customer2, <br />                               book1))<br />mapper.batchLoad(itemsToGet) <br />           // itemsToGet: Map<Class<?>, List<KeyPair>></pre>  |  <pre>enhancedClient.batchGetItem(batchGetItemRequest)<br /><br />enhancedClient.batchGetItem(r -> r.readBatches(<br />    ReadBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addGetItem(i -> i.key(k -> k.partitionValue(0)))<br />             .build(),<br />    ReadBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addGetItem(i -> i.key(k -> k.partitionValue(0)))<br />             .build()))<br /><br />// Iterate over pages with lazy loading or over all items <br />   from the same table.</pre>  | 
|  批量将多个项目写入多个表 **DynamoDB 操作：**`BatchWriteItem`  |  <pre>mapper.batchSave(Arrays.asList(customer1, <br />                               customer2, <br />                               book1)) </pre>  |  <pre>enhancedClient.batchWriteItem(batchWriteItemRequest)<br /><br />enhancedClient.batchWriteItem(r -> r.writeBatches(<br />    WriteBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addPutItem(item1)<br />             .build(),<br />    WriteBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addPutItem(item2)<br />             .build()))</pre>  | 
|  批量删除多个表中的多个项目 **DynamoDB 操作：**`BatchWriteItem`  |  <pre>mapper.batchDelete(Arrays.asList(customer1, <br />                                 customer2, <br />                                 book1)) </pre>  |  <pre>enhancedClient.batchWriteItem(r -> r.writeBatches(<br />    WriteBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addDeleteItem(item1key)<br />             .build(),<br />    WriteBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addDeleteItem(item2key)<br />             .build()))</pre>  | 
|  批量写入/删除多个项目 **DynamoDB 操作：**`BatchWriteItem`  |  <pre>mapper.batchWrite(Arrays.asList(customer1, book1), <br />                  Arrays.asList(customer2)) </pre>  |  <pre>enhancedClient.batchWriteItem(r -> r.writeBatches(<br />    WriteBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addPutItem(item1)<br />             .build(),<br />    WriteBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addDeleteItem(item2key)<br />             .build()))</pre>  | 
|  执行事务性写入 **DynamoDB 操作：**`TransactWriteItems`  |  <pre>mapper.transactionWrite(transactionWriteRequest)</pre>  |  <pre>enhancedClient.transactWriteItems(transasctWriteItemsRequest)</pre>  | 
|  执行事务性读取 **DynamoDB 操作：**`TransactGetItems`  |  <pre>mapper.transactionLoad(transactionLoadRequest)</pre>  |  <pre>enhancedClient.transactGetItems(transactGetItemsRequest) </pre>  | 
|  获取查询中匹配项的计数 **DynamoDB 操作：**使用 `Select.COUNT` 执行 `Query`  |  <pre>mapper.count(Customer.class, queryExpression)</pre>  |  <pre>// Get the count from query results.<br />PageIterable<Customer> pageIterable =<br />    customerTable.query(QueryEnhancedRequest.builder()<br />        .queryConditional(queryConditional)<br />        .select(Select.COUNT)<br />        .build());<br />Iterator<Page<Customer>> iterator = pageIterable.iterator();<br />Page<Customer> page = iterator.next();<br />int count = page.count();<br /><br />// For a more concise approach, you can chain the method calls:<br />int count = customerTable.query(QueryEnhancedRequest.builder()<br />                .queryConditional(queryConditional)<br />                .select(Select.COUNT)<br />                .build())<br />            .iterator().next().count();</pre>  | 
|  获取扫描中匹配项的计数 **DynamoDB 操作：**使用 `Select.COUNT` 执行 `Scan`  |  <pre>mapper.count(Customer.class, scanExpression)</pre>  |  <pre>// Get the count from scan results.<br />PageIterable<Customer> pageIterable =<br />    customerTable.scan(ScanEnhancedRequest.builder()<br />        .filterExpression(filterExpression)<br />        .select(Select.COUNT)<br />        .build());<br />Iterator<Page<Customer>> iterator = pageIterable.iterator();<br />Page<Customer> page = iterator.next();<br />int count = page.count();<br /><br />// For a more concise approach, you can chain the method calls:<br />int count = customerTable.scan(ScanEnhancedRequest.builder()<br />                .filterExpression(filterExpression)<br />                .select(Select.COUNT)<br />                .build())<br />            .iterator().next().count();</pre>  | 
|  在 DynamoDB 中创建与 POJO 类对应的表 **DynamoDB 操作：**`CreateTable`  |  <pre>mapper.generateCreateTableRequest(Customer.class)</pre> 前面的语句生成一个低级别的创建表请求；用户必须在 DynamoDB 客户端中调用 `createTable`。  |  <pre>table.createTable(createTableRequest)<br /><br />table.createTable(r -> r.provisionedThroughput(defaultThroughput())<br />    .globalSecondaryIndices(<br />        EnhancedGlobalSecondaryIndex.builder()<br />            .indexName("gsi_1")<br />            .projection(p -> p.projectionType(ProjectionType.ALL))<br />            .provisionedThroughput(defaultThroughput())<br />            .build()));</pre>  | 
|  在 DynamoDB 中执行并行扫描 **DynamoDB 操作：**使用 `Segment` 和 `TotalSegments` 参数执行 `Scan`  |  <pre>mapper.parallelScan(Customer.class, <br />                    scanExpression, <br />                    numTotalSegments)</pre>  |  用户需要处理工作线程并为每个分段调用 `scan`： <pre>table.scan(r -> r.segment(0).totalSegments(5))</pre>  | 
|  将 Amazon S3 与 DynamoDB 集成以存储智能 S3 链接  |  <pre>mapper.createS3Link(bucket, key)<br />mapper.getS3ClientCache()</pre>  |  不支持，因为它将 Amazon S3 与 DynamoDB 结合在一起。  | 

## 映射类和属性
<a name="dynamodb-mapping-schemas"></a>

在 V1 和 V2 中，都使用 bean 样式的注释将类映射到表。V2 还提供了[其他方法来为特定使用案例定义架构](ddb-en-client-adv-features.md#ddb-en-client-adv-features-schm-overview)，例如使用不可变类。

### bean 注释
<a name="dynamodb-mapping-schemas-annos"></a>

下表显示了 V1 和 V2 中使用的特定使用案例的等效 bean 注释。`Customer` 类场景用于说明参数。

V2 中的注释以及类和枚举遵循驼峰大小写惯例，使用 “” 而不是 “DynamoDB”。DynamoDb


| 使用案例 | V1 | V2 | 
| --- | --- | --- | 
| 将类映射到表 |  <pre>@DynamoDBTable (tableName ="CustomerTable")</pre>  | <pre>@DynamoDbBean<br />@DynamoDbBean(converterProviders = {...})</pre>表名在调用 DynamoDbEnhancedClient\$1table() 方法时定义。 | 
| 将类成员指定为表属性  |  <pre>@DynamoDBAttribute(attributeName = "customerName")</pre>  |  <pre>@DynamoDbAttribute("customerName") </pre>  | 
| 指定班级成员是 hash/partition 关键 |  <pre>@DynamoDBHashKey </pre>  |  <pre>@DynamoDbPartitionKey</pre>  | 
| 指定班级成员是 range/sort 关键 |  <pre>@DynamoDBRangeKey </pre>  |  <pre>@DynamoDbSortKey </pre>  | 
| 将类成员指定为二级索引哈希键/分区键 |  <pre>@DynamoDBIndexHashKey </pre>  |  <pre>@DynamoDbSecondaryPartitionKey </pre>  | 
| 将类成员指定为二级索引范围键/排序键 |  <pre>@DynamoDBIndexRangeKey </pre>  |  <pre>@DynamoDbSecondarySortKey </pre>  | 
| 映射到表时忽略此类成员 |  <pre>@DynamoDBIgnore </pre>  |  <pre>@DynamoDbIgnore</pre>  | 
| 将类成员指定为自动生成的 UUID 键属性 |  <pre>@DynamoDBAutoGeneratedKey</pre>  |  <pre>@DynamoDbAutoGeneratedUuid </pre> 默认情况下，不加载提供此功能的扩展；您必须将扩展添加到客户端生成器中。  | 
| 将类成员指定为自动生成的时间戳属性 |  <pre>@DynamoDBAutoGeneratedTimestamp</pre>  |  <pre>@DynamoDbAutoGeneratedTimestampAttribute</pre> 默认情况下，不加载提供此功能的扩展；您必须将扩展添加到客户端生成器中。  | 
| 将类成员指定为自动递增的版本属性 |  <pre>@DynamoDBVersionAttribute</pre>  |  <pre>@DynamoDbVersionAttribute</pre> 提供此功能的扩展会自动加载。  | 
| 将类成员指定为需要自定义转换 |  <pre>@DynamoDBTypeConverted</pre>  |  <pre>@DynamoDbConvertedBy</pre>  | 
| 将类成员指定为存储为另一个属性类型 |  <pre>@DynamoDBTyped(<DynamoDBAttributeType>)</pre>  |  使用 `AttributeConverter` 实现。V2 为常用 Java 类型提供许多内置转换器。您也可以实施自己的自定义 `AttributeConverter` 或 `AttributeConverterProvider`。请参阅本指南中的[控制属性转换](ddb-en-client-adv-features-conversion.md)。  | 
| 指定一个可以序列化为 DynamoDB 文档（JSON 风格的文档）或子文档的类  |  <pre>@DynamoDBDocument</pre>  | 使用增强型文档 API。请参阅以下资源：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html) | 

### V2 附加注释
<a name="dynamodb-mapping-schemas-annos-v2-addnl"></a>


| 使用案例 | V1 | V2 | 
| --- | --- | --- | 
| 如果 Java 值为 null，则将类成员指定为不存储为 Null 属性 | 不适用 |  <pre>@DynamoDbIgnoreNulls</pre>  | 
| 如果所有属性都为 null，则将类成员指定为空对象 | 不适用 |  <pre>@DynamoDbPreserveEmptyObject</pre>  | 
| 为类成员指定特殊更新操作 | 不适用 |  <pre>@DynamoDbUpdateBehavior</pre>  | 
| 指定一个不可变类 | 不适用 |  <pre>@DynamoDbImmutable</pre>  | 
| 将类成员指定为自动递增的计数器属性 | 不适用 |  <pre>@DynamoDbAtomicCounter</pre> 提供此功能的扩展会自动加载。  | 

## 配置
<a name="dynamodb-mapping-configuration"></a>

在 V1 中，通常使用 `DynamoDBMapperConfig` 的实例来控制特定行为。您可以在创建映射器时或在发出请求时提供配置对象。在 V2 中，配置特定于操作的请求对象。


| 使用案例 | V1 | V1 中的默认设置 | V2 | 
| --- | --- | --- | --- | 
|  |  <pre>DynamoDBMapperConfig.builder()</pre>  |  |  | 
| Batch load/write 重试策略 |  <pre>  .withBatchLoadRetryStrategy(loadRetryStrategy)</pre> <pre>  .withBatchWriteRetryStrategy(writeRetryStrategy)</pre>  | 重试失败的项目 | 在底层 DynamoDBClient 中配置重试策略。请参阅本指南中的[在中配置重试行为 AWS SDK for Java 2.x](retry-strategy.md)。 | 
| 一致性读取 |  <pre>  .withConsistentReads(CONSISTENT)</pre>  | EVENTUAL | 默认情况下，读取操作的一致性读取为 false。在请求对象上使用 .consistentRead(true) 覆盖。 | 
| 包含编组器/解组器集合的转换架构 |  <pre>  .withConversionSchema(conversionSchema)</pre> 静态实现与旧版本向后兼容。  | V2\$1COMPATIBLE | 不适用。这是一项遗留特性，指的是 DynamoDB 的最早版本（V1）存储数据类型的方式，而在增强型客户端中不再保留此行为。DynamoDB V1 中的一个行为示例是将布尔值存储为数字而不是布尔值。 | 
| 表名称 |  <pre>  .withObjectTableNameResolver()<br />  .withTableNameOverride() <br />  .withTableNameResolver()</pre> 静态实现与旧版本向后兼容  | 使用注释或根据类来推断 |  表名在调用 `DynamoDbEnhancedClient#table()` 方法时定义。  | 
| 分页加载策略 |  <pre>  .withPaginationLoadingStrategy(strategy)</pre>  选项包括：LAZY\$1`LOADING`、`EAGER_LOADING` 或 `ITERATION_ONLY`  | LAZY\$1LOADING |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html)  | 
| 请求指标收集 |  <pre>  .withRequestMetricCollector(collector)</pre>  | null | 在构建标准 DynamoDB 客户端时在 ClientOverrideConfiguration 中使用 metricPublisher()。 | 
| 保存行为 |  <pre>  .withSaveBehavior(SaveBehavior.CLOBBER) </pre> 选项包括 `UPDATE`、`CLOBBER`、`PUT`、`APPEND_SET` 或 `UPDATE_SKIP_NULL_ATTRIBUTES`。  | UPDATE |  在 V2 中，您可以显式调用 `putItem()` 或 `updateItem()`。 `CLOBBER or PUT`：V2 中的相应动作是调用 `putItem()`。没有特定的 `CLOBBER` 配置。 `UPDATE`: 对应于 `updateItem()` `UPDATE_SKIP_NULL_ATTRIBUTES`: 对应于`updateItem()`。使用请求设置 `ignoreNulls` 和注释/标签 `DynamoDbUpdateBehavior` 控制更新行为。 `APPEND_SET`：不支持  | 
| 类型转换器工厂 |  <pre>  .withTypeConverterFactory(typeConverterFactory) </pre>  | 标准类型转换器 |  使用以下方式在 bean 上设置 <pre>@DynamoDbBean(converterProviders = {ConverterProvider.class, <br />        DefaultAttributeConverterProvider.class})</pre>  | 

### 每个操作的配置
<a name="dynamodb-mapping-configuration-per-op"></a>

在 V1 中，某些操作（例如 `query()`）可以通过提交给操作的“表达式”对象来进行高度灵活的配置。例如：

```
DynamoDBQueryExpression<Customer> emailBwQueryExpr = new DynamoDBQueryExpression<Customer>()
    .withRangeKeyCondition("Email",
        new Condition()
            .withComparisonOperator(ComparisonOperator.BEGINS_WITH)
            .withAttributeValueList(
                new AttributeValue().withS("my")));

mapper.query(Customer.class, emailBwQueryExpr);
```

在 V2 中，不使用配置对象，而是使用生成器对请求对象设置参数。例如：

```
QueryEnhancedRequest emailBw = QueryEnhancedRequest.builder()
    .queryConditional(QueryConditional
        .sortBeginsWith(kb -> kb
            .sortValue("my"))).build();

customerTable.query(emailBw);
```

## 条件
<a name="dynamodb-mapping-conditionals"></a>

在 V2 中，条件表达式和筛选表达式使用 `Expression` 对象来表达，该对象封装了条件以及名称和筛选条件的映射。


| 使用案例 | 操作 | V1 | V2 | 
| --- | --- | --- | --- | 
| 预期的属性条件 | save()、delete()、query()、scan() |  <pre>new DynamoDBSaveExpression()<br />  .withExpected(Collections.singletonMap(<br />      "otherAttribute", new ExpectedAttributeValue(false)))<br />  .withConditionalOperator(ConditionalOperator.AND);</pre>  | 已弃用；改用 ConditionExpression。 | 
| 条件表达式 | delete() |  <pre>deleteExpression.setConditionExpression("zipcode = :zipcode")<br />deleteExpression.setExpressionAttributeValues(...)<br /></pre>  |  <pre>Expression conditionExpression =<br />    Expression.builder()<br />        .expression("#key = :value OR #key1 = :value1")<br />        .putExpressionName("#key", "attribute")<br />        .putExpressionName("#key1", "attribute3")<br />        .putExpressionValue(":value", AttributeValues.stringValue("wrong"))<br />        .putExpressionValue(":value1", AttributeValues.stringValue("three"))<br />        .build();<br /><br />DeleteItemEnhancedRequest request = DeleteItemEnhancedRequest.builder()<br />         .conditionExpression(conditionExpression).build();</pre>  | 
| 筛选表达式 | query()、scan() |  <pre>scanExpression<br />  .withFilterExpression("#statename = :state")<br />  .withExpressionAttributeValues(attributeValueMapBuilder.build())<br />  .withExpressionAttributeNames(attributeNameMapBuilder.build())<br /></pre>  |  <pre>Map<String, AttributeValue> values = singletonMap(":key", stringValue("value"));<br />Expression filterExpression =<br />    Expression.builder()<br />        .expression("name = :key")<br />        .expressionValues(values)<br />        .build();<br />QueryEnhancedRequest request = QueryEnhancedRequest.builder()<br />    .filterExpression(filterExpression).build();<br /></pre>  | 
| 查询的条件表达式 | query() |  <pre>queryExpression.withKeyConditionExpression()</pre>  |  <pre>QueryConditional keyEqual = QueryConditional.keyEqualTo(b -> b<br />                .partitionValue("movie01"));<br /><br />QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()<br />                .queryConditional(keyEqual)<br />                .build();</pre>  | 

## 类型转换
<a name="dynamodb-mapping-type-conv"></a>

### 默认转换器
<a name="dynamodb-mapping-type-conv-defaults"></a>

在 V2 中，SDK 为所有常见类型提供了一组默认转换器。既可以在整体提供程序级别更改类型转换器，也可以为单个属性更改类型转换器。您可以在 [AttributeConverter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html)API 参考中找到可用转换器的列表。

### 为属性设置自定义转换器
<a name="dynamodb-mapping-type-conv-anno"></a>

在 V1 中，您可以使用 `@DynamoDBTypeConverted` 对 getter 方法添加注释，以指定在 Java 属性类型和 DynamoDB 属性类型之间进行转换的类。例如，`CurrencyFormatConverter` 可以在 Java `Currency` 类型和 DynamoDB 字符串之间应用转换，如以下代码段所示。

```
@DynamoDBTypeConverted(converter = CurrencyFormatConverter.class)
public Currency getCurrency() { return currency; }
```

上一个代码段的 V2 等效代码如下所示。

```
@DynamoDbConvertedBy(CurrencyFormatConverter.class)
public Currency getCurrency() { return currency; }
```

**注意**  
在 V1 中，您可以将注释应用于属性本身、类型或用户定义的注释，V2 仅支持将注释应用于 getter。

### 添加类型转换器工厂或提供程序
<a name="dynamodb-mapping-type-conv-factory"></a>

在 V1 中，您可以提供自己的类型转换器集，也可以通过在配置中添加类型转换器工厂来覆盖您在意的类型。类型转换器工厂扩展 `DynamoDBTypeConverterFactory`，通过获取对默认集的引用并对其进行扩展来完成覆盖。以下代码段演示了如何执行此操作。

```
DynamoDBTypeConverterFactory typeConverterFactory =
    DynamoDBTypeConverterFactory.standard().override()
        .with(String.class, CustomBoolean.class, new DynamoDBTypeConverter<String, CustomBoolean>() {
            @Override
            public String convert(CustomBoolean bool) {
                return String.valueOf(bool.getValue());
            }
            @Override
            public CustomBoolean unconvert(String string) {
                return new CustomBoolean(Boolean.valueOf(string));
            }}).build();
DynamoDBMapperConfig config =
    DynamoDBMapperConfig.builder()
        .withTypeConverterFactory(typeConverterFactory)
        .build();
DynamoDBMapper mapperWithTypeConverterFactory = new DynamoDBMapper(dynamo, config);
```

V2 通过 `@DynamoDbBean` 注释提供了类似的功能。您可以提供单个 `AttributeConverterProvider` 或一个有序的 `AttributeConverterProvider` 链。请注意，如果您提供自己的属性转换器提供程序链，则将覆盖默认的转换器提供程序，且必须在链中包括它才能使用其属性转换器。

```
@DynamoDbBean(converterProviders = {
   ConverterProvider1.class, 
   ConverterProvider2.class,
   DefaultAttributeConverterProvider.class})
public class Customer {
  ...
}
```

本指南中关于[属性转换](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-example)的部分包含了 V2 的完整示例。