Я следую этому документу:
Моя цель — использовать AtomicCounter для генерации уникальных идентификаторов, но я всегда получаю null для обоих примеров:
Мой код выглядит так:
@DynamoDbBean
public class CustomerDocument {
private String root;
private Long updateCounter;
private Long customCounter;
@DynamoDbPartitionKey
public String getRoot() {
return this.root;
}
public void setRoot(String id) {
this.root = id;
}
@DynamoDbAtomicCounter
public Long getUpdateCounter() {
return this.updateCounter;
}
public void setUpdateCounter(Long counter) {
this.updateCounter = counter;
}
@DynamoDbAtomicCounter(delta = 5, startValue = 10)
public Long getCustomCounter() {
return this.customCounter;
}
public void setCustomCounter(Long counter) {
this.customCounter = counter;
}
}
хранилище
CustomerDocument document = new CustomerDocument();
document.setRoot(root);
customerTable.updateItem(document);
CustomerDocument retrievedCustomer = customerTable.getItem(document);
retrievedCustomer.getUpdateCounter(); // null
retrievedCustomer.getCustomCounter(); // null
customerTable.updateItem(document);
retrievedCustomer = orderCounterTable.getItem(document);
retrievedCustomer.getUpdateCounter(); // null
retrievedCustomer.getCustomCounter(); // null
Любая идея о проблеме, пожалуйста?
Редактировать
на основе ответа выше мой код теперь выглядит так:
public CustomerDocument nextCounter(String root) {
CustomerDocument document = new CustomerDocument();
document.setId(root);
CustomerDocument item = orderCounterTable.getItem(document);
if (item == null) {
CustomerDocument defaultDocument = new CustomerDocument();
defaultDocument.setId(root);
defaultDocument.setCount(1L);
customerTable.putItem(defaultDocument);
return defaultDocument;
} else {
CustomerDocument newDocument = new CustomerDocument();
newDocument.setId(item.getId());
return customerTable.updateItem(newDocument);
}
}
Но я все равно получаю null каждый orderCounterTable.updateItem(newDocument):
Я получаю только:
{
"id": "20042024"
}




Эта функция работает так, как показано в примере бессерверного приложения для управления фоторесурсами, в котором используется DynamoDbAtomicCounter.
В этом примере внешний интерфейс — это приложение React. Серверная часть использует AWS SDK для Java V2. Каждый раз, когда приложение находит новую метку с помощью Amazon Rekognition, столбец счетчика в таблице Amazon DynamoDB увеличивается с помощью DynamoDbAtomicCounter. Вот пользовательский интерфейс React. Вы можете увидеть количество для каждой метки.
Вот применимый код, который заставляет его работать.
Это класс DynamoDB, который использует необходимые аннотации, такие как @DynamoDbAtomicCounter.
package com.example.photo;
import software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbAtomicCounter;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import java.util.List;
@DynamoDbBean
public class Label {
private String id;
private Integer count;
private List<String> images;
@DynamoDbPartitionKey
public String getId() {
return this.id;
};
public void setId(String id) {
this.id = id;
}
@DynamoDbAtomicCounter (startValue = 1)
public Integer getCount() {
return this.count;
}
public void setCount(Integer count) {
this.count = count;
}
public List<String> getImages() {
return this.images;
}
public void setImages(List<String> images) {
this.images = images;
}
}
Вот метод, где он используется с Enhanced Client:
private void addSingleRecord(DynamoDbTable<Label> table, String tag, String key) {
// Check to see if the label exists in the Amazon DynamoDB table.
// The count item uses an @DynamoDbAtomicCounter which means it is
// updated automatically. No need to manually set this value when the record is
// created or updated.
if (!checkTagExists(table, tag)) {
Label photoRec = new Label();
photoRec.setId(tag);
List<String> keyList = new ArrayList<>();
keyList.add(key);
photoRec.setImages(keyList);
table.putItem(photoRec);
} else {
// The tag exists in the table.
Key myKey = Key.builder()
.partitionValue(tag)
.build();
// Add the file name to the list.
Label myPhoto = table.getItem(myKey);
Label updatedPhoto = new Label();
List<String> imageList = myPhoto.getImages();
imageList.add(key);
updatedPhoto.setId(tag);
updatedPhoto.setImages(imageList);
table.updateItem(updatedPhoto);
}
}
ОБНОВЛЯТЬ
Обратите внимание, что здесь есть хитрость — от команды SDK:
«Я понял, что происходит. Это потому, что мы повторно используем тот же объект, который мы читаем из базы данных с помощью «getItem». Если вы создаете новый объект и устанавливаете данные, он работает».
Это может быть причиной вашей проблемы. Создайте новый объект, установите данные, и произойдет приращение. Обратите внимание, что здесь я создаю новый объект:
Label updatedPhoto = new Label();
List<String> imageList = myPhoto.getImages();
imageList.add(key);
updatedPhoto.setId(tag);
updatedPhoto.setImages(imageList);
table.updateItem(updatedPhoto);
Вы можете найти этот полный пример в Библиотеке кода AWS. Вы можете закодировать серверную часть и использовать AWS CDK для установки ресурсов и запуска этого приложения. Следуйте указаниям в документе и следуйте инструкциям CDK. После того, как вы выполните все, вы увидите приложение в действии и работающий DynamoDbAtomicCounter.
Видеть:
ОБНОВЛЕНИЕ ВАШЕГО КОДА
Мне пришлось внести несколько изменений в ваш код.
КОД:
EnhancedAtomicCounter
package com.example.dynamodb.enhanced.test;
import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
public class EnhancedAtomicCounter {
public static void main(String[] args) {
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
Region region = Region.US_EAST_1;
DynamoDbClient ddb = DynamoDbClient.builder()
.credentialsProvider(EnvironmentVariableCredentialsProvider.create())
.region(region)
.build();
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
.dynamoDbClient(ddb)
.build();
String root = "1000";
putCustObj(enhancedClient, root);
updateRec(enhancedClient, root);
updateRec2(enhancedClient, root);
}
public static void putCustObj(DynamoDbEnhancedClient enhancedClient, String root) {
DynamoDbTable<CustomerDocument> mappedTable = enhancedClient.table("CustomerDocument", TableSchema.fromBean(CustomerDocument.class));
CustomerDocument document = new CustomerDocument();
document.setRoot(root);
document.setName("Scott");
document.setCustomCounter(200L);
// Put the customer data into an Amazon DynamoDB table.
mappedTable.putItem(document);
}
public static void updateRec(DynamoDbEnhancedClient enhancedClient, String root) {
DynamoDbTable<CustomerDocument> mappedTable = enhancedClient.table("CustomerDocument", TableSchema.fromBean(CustomerDocument.class));
Key key = Key.builder()
.partitionValue(root)
.build();
// Get the item by using the key.
CustomerDocument result = mappedTable.getItem(r->r.key(key));
// Create a new object so @DynamoDbAtomicCounter works
CustomerDocument newCustOb = new CustomerDocument();
newCustOb.setRoot(result.getRoot());
newCustOb.setName("Scott2");
mappedTable.updateItem(newCustOb);
}
public static void updateRec2(DynamoDbEnhancedClient enhancedClient, String root) {
DynamoDbTable<CustomerDocument> mappedTable = enhancedClient.table("CustomerDocument", TableSchema.fromBean(CustomerDocument.class));
Key key = Key.builder()
.partitionValue(root)
.build();
// Get the item by using the key.
CustomerDocument result = mappedTable.getItem(r->r.key(key));
// Create a new object so @DynamoDbAtomicCounter works
CustomerDocument newCustOb = new CustomerDocument();
newCustOb.setRoot(result.getRoot());
newCustOb.setName("Scott3");
mappedTable.updateItem(newCustOb);
System.out.println("Item updated!");
}
}
КлиентДокумент
package com.example.dynamodb.enhanced.test;
import software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbAtomicCounter;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
@DynamoDbBean
public class CustomerDocument {
private String root;
private String name;
private Long updateCounter;
private Long customCounter;
@DynamoDbPartitionKey
public String getRoot() {
return this.root;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public void setRoot(String id) {
this.root = id;
}
@DynamoDbAtomicCounter (startValue = 1)
public Long getUpdateCounter() {
return this.updateCounter;
}
public void setUpdateCounter(Long counter) {
this.updateCounter = counter;
}
@DynamoDbAtomicCounter(delta = 5, startValue = 10)
public Long getCustomCounter() {
return this.customCounter;
}
public void setCustomCounter(Long counter) {
this.customCounter = counter;
}
}
В моем примере я сделал несколько обновлений записи, изменив имя. Сейчас
updateCounter должно быть 3. Это:
Смотрите мое обновление здесь. ОТ команды SDK: «Я понял, что происходит. Это потому, что мы повторно используем тот же объект, который мы считываем из базы данных с помощью «getItem». Если вы создаете новый объект и устанавливаете данные, он работает». См. этикетку updatedPhoto. это новый объект, который я использую для обновления таблицы.
спасибо за ваш ответ, я использовал тот же трюк, но я все еще получаю нуль для счетчика, вы можете проверить мой новый код в моем ответе, пожалуйста.
Я могу понять схему вашего стола. Я попытаюсь воспроизвести вашу таблицу и ваш код. Я хочу посмотреть, смогу ли я воспроизвести вашу проблему
Я опубликую свои выводы.
Я сделал несколько модификаций вашего кода, и теперь он отлично работает. 2 элемента с @DynamoDbAtomicCounter обновляются, как показано на моем снимке экрана.
Я понял, почему мое решение не работает :), пожалуйста, проверьте мой ответ здесь
Сравнивая свой код и код @smac2020, я понимаю, что использую .extensions(VersionedRecordExtension.builder().build()):
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
.dynamoDbClient(amazonDynamoDB())
--> //.extensions(VersionedRecordExtension.builder().build())
.build();
Удалив эту конфигурацию, мое решение работает нормально.
мой окончательный код был просто:
public CustomerDocument nextCounter(String root) {
CustomerDocument newDocument = new CustomerDocument();
newDocument.setRoot(root);
return customerTable.updateItem(newDocument);
}
Ни putItem, ничего другого.
Рад, что это работает
Эй, спасибо за ваш ответ, я использовал ту же логику, и я все еще получаю нуль для счетчика, я не понимаю, что вы подразумеваете под
This functionality works fine as long as you setup the code correctlyчто не так с моим кодом !?