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

mck*_*mey 14 java amazon-web-services amazon-dynamodb

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

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

Dav*_*cek 18

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

  • HashKeyElementRangeKeyElement将替换为Map <String,AttributeValue>.这包括名为ExclusiveStartKey,LastEvaluatedKeyKey的结构.这种变化对代码的主要影响是,现在为了调用GetItem,您的代码需要知道主键的属性名称,而不仅仅是主键值.
  • Query现在使用Map <String,Condition>类型的KeyCondition来指定完整查询,而不是使用单独的HashKeyValueRangeKeyCondition字段.
  • CreateTable输入将属性类型定义与主键定义分开(并且create/update/delete/describe响应与此匹配)
  • 响应中的消耗容量现在是结构而不是单个数字,并且必须在请求中被要求.在批处理操作中,这将在单独的ConsumedCapacity结构中返回,而不是与结果一起返回.

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

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


mck*_*mey 9

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

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

首先,更改DynamoDB命名空间:

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

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

接下来,非常仔细地查找/替换被泛型集合替换的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合并withHashKeyValue(AttributeValue) withRangeKeyCondition(Condition)到mega中withKeyConditions(Map<String,Condition>) 此方法是LSI的核心更改,允许您指定除散列/范围之外的其他内容.它接受的内容比接口更具限制性,但是当您考虑DynamoDB仅允许您查询索引属性时,这是合乎逻辑的.
  • DynamoDBQueryExpression 变得通用并改变了它的界面(不知道为什么).
  • KeySchemaElement不再需要AttributeType,但现在需要KeyType

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

PS当我执行所有这些时,版本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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Java的泛型中的类型擦除使得这一点再次变得更加丑陋.您有时需要明确指定VType:

new GetItemRequest().withKey(MakeJavaSuckLess.<AttributeValue>asMap("hashKey", new AttributeValue("hashVal"), "rangeKey", new AttributeValue("rangeVal")));
Run Code Online (Sandbox Code Playgroud)

  • 受此stackoverflow问题和地图制作者提示的启发,我撰写了一篇关于使用Google Guava的Map Builders的博客文章以及一些其他提示[使用DynamoDB的Java SDK编写更少的代码](https://java.awsblog.com/post/Tx2VOZ8V9I67LLD /写作,不太代码时,使用最AWS-SDK-用于Java的).我希望它有所帮助! (3认同)