AWS Java SDK中DynamoDB v2的迁移详细信息?

时间:2013-05-17 15:06:59

标签: java amazon-web-services amazon-dynamodb

是否有人在AWS Java SDK 1.4.2(及更高版本)中对DynamoDB的新命名空间(com.amazonaws.services.dynamodbv2)和接口进行了更改?根据{{​​3}},本地中学指数的发布显然需要进行重大修改。

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

2 个答案:

答案 0 :(得分:17)

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

  • HashKeyElement RangeKeyElement 将替换为 Map&lt; String,AttributeValue&gt; 。这包括名为 ExclusiveStartKey LastEvaluatedKey Key 的结构。这种变化对代码的主要影响是,现在为了调用 GetItem ,您的代码需要知道主键的属性名称,而不仅仅是主键值。< / LI>
  • 查询现在使用 Map&lt; String,Condition&gt; 类型的 KeyCondition 指定完整查询,而不是单独的 HashKeyValue 和< em> RangeKeyCondition 字段。
  • CreateTable输入将属性类型定义与主键定义分开(并创建/更新/删除/描述响应与此匹配)
  • 响应中的消耗容量现在是结构而不是单个数字,并且必须在请求中被要求。在批处理操作中,这将在单独的 ConsumedCapacity 结构中返回,而不是与结果一起返回。

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

如果使用新API创建包含本地辅助索引的表,您仍可以使用 dynamodb 命名空间中的现有代码来执行该表上的所有现有操作。例如,带有 dynamodb 命名空间客户端的PutItem将对使用 dynamodbv2 客户端创建的表进行处理,以及相反的方式。

答案 1 :(得分:9)

DynamoDB AWS Java 1.4.1 =&gt; 1.4.2(非详尽的)迁移步骤

好吧,我咬了一下子弹做了。这是我的经历。

首先,更改DynamoDB命名空间:

  • com.amazonaws.services.dynamodb =&gt; com.amazonaws.services.dynamodbv2

您注意到的第一件事是缺少类型。最重要的是Key已经不见了。很好的摆脱,因为它太通用的名称。 它现在被替换为Map,因为密钥变得更具有Local Secondary Indexes(LSI)的可塑性。 不幸的是,使用地图和泛型一般很糟糕(参见底部的奖金)。 withHashKeyElement / withRangeKeyElement的流畅界面已经一去不复返了。

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

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

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

  • 查找每个new Map<String, AttributeValue>,表明Key以前就在那里。
  • QueryRequestwithHashKeyValue(AttributeValue) withRangeKeyCondition(Condition)合并到了巨型withKeyConditions(Map<String,Condition>)中 此方法是LSI的核心更改,允许您指定散列/范围以外的内容。它接受的内容比界面更具限制性,但是当您考虑DynamoDB只允许您查询索引属性时,这是合乎逻辑的。
  • DynamoDBQueryExpression变得通用并改变了界面(不确定原因)。
  • KeySchemaElement不再需要AttributeType,但现在需要KeyType

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

P.S。当我执行所有这些时,version 1.4.4.1刚刚发布到Maven Central。


<强>加成

由于Maps是Java缺乏松散类型类的常见解决方案,因此它们无处不在。 一个小帮助库可以真正走向建立这些不那么冗长的方式。 以下是我帮助的一些内容:

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的泛型中的

Type erasure使得这一点再次变得更加丑陋。您有时需要明确指定VType

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