

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

# 迁移到适用于 DynamoDB 的 Java 客户端加密库的版本 3.x
<a name="ddb-java-migrate"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x* 是对 2.*x* 代码库的重大改写。它包括许多更新，例如新的结构化数据格式、改进的多租户支持、无缝架构更改，以及可搜索的加密支持。本主题提供有关如何将代码迁移到版本 3.*x* 的指导。

## 从版本 1.x 迁移到 2.x
<a name="ddb-java-v1-to-v2"></a>

在迁移到版本 3.*x* 之前先迁移到版本 2.*x*。版本 2.*x* 已将最新提供程序的符号从 `MostRecentProvider` 更改为 `CachingMostRecentProvider`。如果您当前使用的是带有 `MostRecentProvider` 符号的适用于 DynamoDB 的 Java 客户端加密库的版本 1.*x*，必须将代码中的符号名称更新为 `CachingMostRecentProvider`。要了解更多信息，请参阅[最新提供程序的更新](most-recent-provider.md#mrp-versions)。

## 从版本 2.x 迁移到 3.x
<a name="ddb-java-v2-to-v3"></a>

以下步骤说明如何将您的代码从适用于 DynamoDB 的 Java 客户端加密库的版本 2.*x* 迁移到版本 3.*x*。

### 步骤 1：准备读取新格式的项目
<a name="ddb-java-migrate-step1"></a>

完成以下步骤，准备您的 AWS 数据库加密 SDK 客户端，以读取新格式的项目。部署以下更改后，您的客户端将继续以与版本 2.*x* 相同的行为方式运行。您的客户将继续读取和写入 2.*x* 格式中的项目，但是这些更改使客户端做好[读取新格式项目](#ddb-java-migrate-step2)的准备。

**将你的版本更新 适用于 Java 的 AWS SDK 到 2.x 版**  
适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x* 需要 [DynamoDB 增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)。DynamoDB 增强版客户端取代了之前版本[中使用的 DBMapper](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html) Dynamo。要使用增强型客户端，您必须使用 AWS SDK for Java 2.x。  
按照[从 适用于 Java 的 AWS SDK的版本 1.x 迁移到 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html) 的说明进行操作。  
有关需要哪些 AWS SDK for Java 2.x 模块的更多信息，请参阅[先决条件](ddb-java.md#ddb-java-prerequisites)。

**配置您的客户端，以读取由旧版本加密的项目**  
以下过程概述了以下代码示例中所演示的步骤。  

1. 创建一个[密钥环](keyrings.md)。

   密钥环和[加密材料管理程序](concepts.md#crypt-materials-manager)将取代以前版本的适用于 DynamoDB 的 Java 客户端加密库中使用的加密材料提供程序。
**重要**  
您在创建密钥环时指定的包装密钥必须与版本 2.*x* 中用于加密材料提供程序的包装密钥相同。

1. 创建一个带注释的类的表架构。

   此步骤用于定义开始以新格式编写项目时将使用的属性操作。

   有关使用全新 DynamoDB 增强版客户端的指南，请参阅《适用于 Java 的 AWS SDK 开发人员指南》**中的[生成一个 `TableSchema`](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html)。

   以下示例假设您已使用新的属性操作注释从版本 2.*x* 中更新您的带注释类。有关为属性操作添加注释的更多指导，请参阅 [使用带注释的数据类](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。
**注意**  
如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。有关显示用于定义的注释的示例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，请参阅 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass4.java)。

1. 定义[从签名中可以排除哪些属性](ddb-java-using.md#allowed-unauth)。

1. 配置在 2.x 版本建模类中配置的属性操作的显式映射。

   此步骤定义用于以旧格式编写项目的属性操作。

1. 配置 `DynamoDBEncryptor` 您在适用于 DynamoDB 的 Java 客户端加密库的版本 2.*x* 中使用的 。

1. 配置遗留行为。

1. 创建 `DynamoDbEncryptionInterceptor`。

1. 创建一个新的 AWS SDK DynamoDB 客户端。

1. 创建 `DynamoDBEnhancedClient` 并使用您的建模类创建表。

   要了解 DynamoDB 增强版客户端的更多信息，请参阅[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep1 {

    public static void MigrationStep1(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Create a Keyring.
        //    This example creates an AWS KMS Keyring that specifies the 
        //    same kmsKeyId previously used in the version 2.x configuration.
        //    It uses the 'CreateMrkMultiKeyring' method to create the 
        //    keyring, so that the keyring can correctly handle both single
        //    region and Multi-Region KMS Keys.
        //    Note that this example uses the AWS SDK for Java v2 KMS client.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        // 2. Create a Table Schema over your annotated class.
        //    For guidance on using the new attribute actions 
        //    annotations, see SimpleClass.java in the 
        //    aws-database-encryption-sdk-dynamodb GitHub repository. 
        //    All primary key attributes must be signed but not encrypted 
        //    and by default all non-primary key attributes 
        //    are encrypted and signed (ENCRYPT_AND_SIGN).
        //    If you want a particular non-primary key attribute to be signed but
        //    not encrypted, use the 'DynamoDbEncryptionSignOnly' annotation.
        //    If you want a particular attribute to be neither signed nor encrypted
        //    (DO_NOTHING), use the 'DynamoDbEncryptionDoNothing' annotation.
        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        // 3. Define which attributes the client should expect to be excluded 
        //    from the signature when reading items.
        //    This value represents all unsigned attributes across the entire 
        //    dataset.
        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");

        // 4. Configure an explicit map of the attribute actions configured 
        //    in your version 2.x modeled class.
        final Map<String, CryptoAction> legacyActions = new HashMap<>();
        legacyActions.put("partition_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("sort_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
        legacyActions.put("attribute2", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute3", CryptoAction.DO_NOTHING);

        // 5. Configure the DynamoDBEncryptor that you used in version 2.x.
        final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient();
        final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId);
        final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp);

        // 6. Configure the legacy behavior.
        //    Input the DynamoDBEncryptor and attribute actions created in 
        //    the previous steps. For Legacy Policy, use 
        //    'FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy continues to read 
        //    and write items using the old format, but will be able to read
        //    items written in the new format as soon as they appear.
        final LegacyOverride legacyOverride = LegacyOverride
                .builder()
                .encryptor(oldEncryptor)
                .policy(LegacyPolicy.FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT)
                .attributeActionsOnEncrypt(legacyActions)
                .build();

        // 7. Create a DynamoDbEncryptionInterceptor with the above configuration.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .legacyOverride(legacyOverride)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 8. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 7.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 9. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb client 
        //    created in Step 8, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

### 步骤 2：用新格式编写项目
<a name="ddb-java-migrate-step2"></a>

将步骤 1 中的更改部署到所有读取器后，请完成以下步骤，将 AWS 数据库加密 SDK 客户端配置为以新格式写入项目。部署以下更改后，您的客户端将继续读取旧格式的项目，并且开始以新格式编写和读取项目。

以下过程概述了以下代码示例中所演示的步骤。

1. 继续配置密钥环、表架构、旧属性操作 `allowedUnsignedAttributes` 和 `DynamoDBEncryptor`，就像在[**步骤 1**](#ddb-java-migrate-step1) 中执行的操作一样。

1. 将遗留行为更新为仅使用新格式编写新项目。

1. 创建 `DynamoDbEncryptionInterceptor `

1. 创建一个新的 AWS SDK DynamoDB 客户端。

1. 创建 `DynamoDBEnhancedClient` 并使用您的建模类创建表。

   要了解 DynamoDB 增强版客户端的更多信息，请参阅[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep2 {

    public static void MigrationStep2(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Continue to configure your keyring, table schema, legacy 
        //    attribute actions, allowedUnsignedAttributes, and 
        //    DynamoDBEncryptor as you did in Step 1.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");

        final Map<String, CryptoAction> legacyActions = new HashMap<>();
        legacyActions.put("partition_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("sort_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
        legacyActions.put("attribute2", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute3", CryptoAction.DO_NOTHING);

        final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient();
        final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId);
        final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp);

        // 2. Update your legacy behavior to only write new items using the new
        //    format. 
        //    For Legacy Policy, use 'FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy
        //    continues to read items in both formats, but will only write items
        //    using the new format.
        final LegacyOverride legacyOverride = LegacyOverride
                .builder()
                .encryptor(oldEncryptor)
                .policy(LegacyPolicy.FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT)
                .attributeActionsOnEncrypt(legacyActions)
                .build();

        // 3. Create a DynamoDbEncryptionInterceptor with the above configuration.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .legacyOverride(legacyOverride)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 4. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 3.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 5. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb Client created
        //    in Step 4, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

部署步骤 2 的更改后，必须使用新格式重新加密表中的所有旧项目，然后才能继续执行[步骤 3](#ddb-java-migrate-step3)。您无法运行单一指标或查询来快速加密您的现有项目。使用对您的系统最有意义的过程。例如，您可以使用异步过程，以缓慢扫描表，然后使用您定义的新属性操作和加密配置重写项目。

### 步骤 3：只能以新格式读取和编写项目
<a name="ddb-java-migrate-step3"></a>

使用新格式重新加密表格中的所有项目后，您可以从配置中移除遗留行为。完成以下步骤以将客户端配置为仅以新格式读取和编写项目。

以下过程概述了以下代码示例中所演示的步骤。

1. 继续配置密钥环、表架构和 `allowedUnsignedAttributes`，就像在[**步骤 1**](#ddb-java-migrate-step1) 中执行的操作一样。从您的配置中移除旧属性操作和 `DynamoDBEncryptor`。

1. 创建 `DynamoDbEncryptionInterceptor`。

1. 创建一个新的 AWS SDK DynamoDB 客户端。

1. 创建 `DynamoDBEnhancedClient` 并使用您的建模类创建表。

   要了解 DynamoDB 增强版客户端的更多信息，请参阅[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep3 {

    public static void MigrationStep3(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Continue to configure your keyring, table schema,
        //    and allowedUnsignedAttributes as you did in Step 1.
        //    Do not include the configurations for the DynamoDBEncryptor or 
        //    the legacy attribute actions.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");


        // 3. Create a DynamoDbEncryptionInterceptor with the above configuration.
        //    Do not configure any legacy behavior.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 4. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 3.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 5. Create the DynamoDbEnhancedClient using the AWS SDK Client 
        //    created in Step 4, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```