Сведения о миграции для DynamoDB v2 в AWS Java SDK?
Кто-нибудь внес изменения в новые пространства имен (com.amazonaws.services.dynamodbv2
) и интерфейсы для DynamoDB в AWS Java SDK 1.4.2 (и позже)? Выпуск локальных вторичных индексов, по-видимому, потребовал нарушения изменений примечаний к выпуску 1.4.2.
Кто-нибудь нашел руководство, в котором подробно описано, что изменилось и что должно произойти, чтобы перенести существующий код? Я пытаюсь решить, когда лучше всего сделать это изменение для существующей базы кода.
Ответы
Ответ 1
Новое пространство имен dynamodbv2 DynamoDB вводит следующие несовместимые изменения (в том смысле, что они не являются просто аддитивными и требуют изменения кода для переключения в новое пространство имен):
- HashKeyElement и RangeKeyElement заменяются на Map < String, AttributeValue > . Сюда входят структуры ExclusiveStartKey, LastEvaluatedKey и Key. Основное влияние на код с этим изменением заключается в том, что теперь для вызова GetItem, например, ваш код должен знать имена атрибутов первичных ключей, а не только значения первичного ключа.
- Теперь Query использует KeyCondition типа Map < String, Condition > , чтобы указать полный запрос, вместо отдельных полей HashKeyValue и RangeKeyCondition.
- Ввод CreateTable отделяет определения типа атрибута от определений первичных ключей (и создает/обновляет/удаляет/описывает ответы).
- Потребляемая мощность в ответах теперь представляет собой структуру вместо одного номера и должна запрашиваться в запросе. В пакетных операциях это возвращается в отдельной структуре ConsumedCapacity, а не рядом с результатами.
При необходимости можно перенести свой код на новый API Java по мере необходимости. Если вы планируете добавить функциональность к вашему коду, который запрашивает локальные вторичные индексы или создает таблицы с локальными вторичными индексами, вам нужно будет использовать новый API для этой части вашего кода.
Если вы создаете таблицу с локальными вторичными индексами с новым API, вы все равно можете использовать свой существующий код в пространстве имен dynamodb для выполнения всех существующих операций в этой таблице. Например, PutItem с клиентом пространства имен dynamodb будет работать против таблиц, созданных с помощью клиента dynamodbv2, а также наоборот.
Ответ 2
DynamoDB AWS Java 1.4.1 = > 1.4.2 (не исчерпывающие) шаги миграции
Хорошо, я укусил пулю и сделал это. Вот мой опыт.
Сначала измените пространство имен DynamoDB:
-
com.amazonaws.services.dynamodb
= > com.amazonaws.services.dynamodbv2
Первое, что вы заметили, - это недостающие типы. Самый главный из них - Key. Хорошее избавление, поскольку оно было слишком общим названием.
Теперь он заменен на карту, которая имеет смысл, поскольку ключи становятся намного более податливыми с Local Secondary Indexes (LSI).
К сожалению, работа с картами и дженериками в целом отстой в Java (см. Бонус внизу).
Gone - это плавные интерфейсы 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)
в мега withKeyConditions(Map<String,Condition>)
Этот метод является основным изменением для LSI, позволяющим указывать другие объекты, кроме хэша/диапазона. То, что оно принимает, является более ограничительным, чем интерфейс, но это логично, если вы считаете, что DynamoDB позволяет запрашивать индексированные атрибуты.
-
DynamoDBQueryExpression
стал общим и изменил его интерфейс (не уверен, почему).
-
KeySchemaElement
больше не требуется AttributeType
, но теперь требуется KeyType
Наконец, компиляция и регрессия проверяют весь ваш стек.
P.S. Пока я выполнял все это, версия 1.4.4.1 была выпущена только в Maven Central.
Bonus
Так как 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"));
Тип erasure в Java-дженериках делает это снова уродливым в местах. Иногда вам нужно явно указать VType
:
new GetItemRequest().withKey(MakeJavaSuckLess.<AttributeValue>asMap("hashKey", new AttributeValue("hashVal"), "rangeKey", new AttributeValue("rangeVal")));