AWS Java 开发工具包中 DynamoDB v2 的迁移详细信息?

是否有人在 AWS Java 开发工具包 1.4.2(及更高版本)中对 DynamoDB 的新命名空间 () 和接口进行了更改?本地二级指数的发布显然需要根据1.4.2发行说明进行重大更改。com.amazonaws.services.dynamodbv2

有没有人找到一个指南,详细说明了哪些更改以及迁移现有代码需要发生什么?我正在尝试决定何时最好地对现有代码库进行此更改。


答案 1

DynamoDB 的新 dynamodbv2 命名空间引入了以下不兼容的更改(因为它们不是简单的累加,并且需要更改代码才能切换到新的命名空间):

  • HashKeyElementRangeKeyElement替换为 Map<String、AttributeValue>。这包括名为 ExclusiveStartKeyLastEvaluatedKeyKey 的结构。此更改对代码的主要影响是,例如,现在为了调用 GetItem,您的代码需要知道主键的属性名称,而不仅仅是主键值。
  • 查询现在使用 Map<String、Condition> 类型的 KeyCondition 来指定完整查询,而不是具有单独的 HashKeyValueRangeKeyCondition 字段。
  • CreateTable 输入将属性类型定义与主键定义分开(并且创建/更新/删除/描述响应与此匹配)
  • 响应中的已消耗容量现在是一个结构,而不是单个数字,必须在请求中要求。在 Batch 操作中,这将在单独的“消耗容量”结构中返回,而不是与结果一起返回。

如果需要,可以将代码增量迁移到新的 Java API。如果您计划向代码添加查询本地二级索引的功能,或者使用本地二级索引创建表,则需要对该部分代码使用新的 API。

如果您使用新 API 创建具有本地二级索引的表,您仍然可以使用 dynamodb 命名空间中的现有代码对该表执行所有现有操作。例如,具有 dynamodb 命名空间客户端的 PutItem 将针对使用 dynamodbv2 客户端创建的表,反之亦然。


答案 2

DynamoDB AWS Java 1.4.1 = > 1.4.2(非详尽)迁移步骤

好吧,我咬紧牙关,做到了。这是我的经验。

首先,更改 DynamoDB 命名空间:

  • com.amazonaws.services.dynamodb => com.amazonaws.services.dynamodbv2

您注意到的第一件事是缺少类型。最主要的是Key已经消失了。很好,因为它的名字太通用了。它现在被Map所取代,这是有道理的,因为键通过本地二级索引(LSI)变得更具延展性。不幸的是,在Java中使用地图和泛型通常很糟糕(请参阅底部的奖金)。/ 的流畅接口已经一去不复返了。withHashKeyElementwithRangeKeyElement

接下来,非常仔细地查找/替换被泛型集合替换的 DynamoDB 类型:

  • com.amazonaws.services.dynamodb.model.Key => Map<String, AttributeValue>
  • com.amazonaws.services.dynamodb.model.BatchResponse => List<Map<String, AttributeValue>>
  • com.amazonaws.services.dynamodb.model.KeySchema => List<KeySchemaElement>
  • (可能是其他人,这些是我直接引用的少数几个。

接下来,找到所有损坏的东西。这是一个非常手动的过程,需要很好地了解您的代码库和SDK。具体来说,您必须非常了解您的密钥架构,因为它都是从现在开始的字符串。幸运的是,在我的情况下,前两个任务大约是90%的变化:

  • 找到每一个,这是以前存在的一个迹象。new Map<String, AttributeValue>Key
  • QueryRequest合并到 mega withKeyConditions(Map<String,Condition>) 此方法是 LSI 的核心更改,允许您指定哈希/范围以外的内容。它接受的内容比接口更具限制性,但当您认为 DynamoDB 仅允许您查询索引属性时,这是合乎逻辑的。withHashKeyValue(AttributeValue)withRangeKeyCondition(Condition)
  • DynamoDBQueryExpression变得通用并更改了其界面(不知道为什么)。
  • KeySchemaElement不再需要,但现在需要AttributeTypeKeyType

最后,编译和回归测试整个堆栈。

附言:当我执行所有这些操作时,版本1.4.4.1刚刚发布到Maven Central。


奖金

由于Maps是Java缺乏松散类型类的常见解决方案,因此它们无处不在。一个小小的辅助 lib 真的可以大大有助于构建这些不那么冗长的内容。以下是我的助手的一些内容:

public class MakeJavaSuckLess { // TODO: find a shorter class name
    public static final float MAX_LOAD_FACTOR = 1.0f;

    /**
     * Builds a mutable Map from an interlaced sequence of key-value pairs
     * where keys are strings and values are VType objects
     * @param pairs
     * @return
     */
    public static <VType> Map<String, VType> asMap(Object... pairs) {
        return mergeMaps(null, pairs);
    }

    /**
     * Builds a mutable Map from an interlaced sequence of key-value pairs
     * where keys are strings and values are VType objects
     * @param pairs
     * @return
     */
    public static <VType> Map<String, VType> mergeMaps(Map<String, VType> map, Object... pairs) {
        final int length = (pairs != null) ? pairs.length/2 : 0;
        if (map == null) {
            // max out the load factor since most of these don't change
            map = new HashMap<String, VType>(length, MAX_LOAD_FACTOR);
        }

        for (int i=0; i<length; i++) {
            String key = asString(pairs[2*i]);
            @SuppressWarnings("unchecked")
            VType value = (VType)pairs[2*i+1];
            map.put(key, value);
        }
        return map;
    }
}

现在,创建 DynamoDB 密钥稍微不那么难看了:

Map<String, AttributeValue> key = MakeJavaSuckLess.asMap("hashKey", new AttributeValue("hashVal"), "rangeKey", new AttributeValue("rangeVal"));

Java泛型中的类型擦除使这在其他地方再次更加丑陋。您有时需要显式指定:VType

new GetItemRequest().withKey(MakeJavaSuckLess.<AttributeValue>asMap("hashKey", new AttributeValue("hashVal"), "rangeKey", new AttributeValue("rangeVal")));

推荐