Skip to content

Commit a7a5344

Browse files
Add partial update to DynamoDbTemplate using UpdateItemEnhancedRequest (#1448)
Fixes #1447
1 parent 211a798 commit a7a5344

File tree

3 files changed

+55
-8
lines changed

3 files changed

+55
-8
lines changed

spring-cloud-aws-dynamodb/src/main/java/io/awspring/cloud/dynamodb/DynamoDbOperations.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
import software.amazon.awssdk.enhanced.dynamodb.model.PageIterable;
2121
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;
2222
import software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest;
23+
import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedRequest;
2324

2425
/**
2526
* Interface for simple DynamoDB template operations.
2627
*
2728
* @author Matej Nedic
29+
* @author Marcus Voltolim
2830
* @since 3.0.0
2931
*/
3032
public interface DynamoDbOperations {
@@ -45,6 +47,14 @@ public interface DynamoDbOperations {
4547
*/
4648
<T> T update(T entity);
4749

50+
/**
51+
* Updates Entity with configurations like ignore null to DynamoDB table.
52+
*
53+
* @param request - UpdateItemEnhancedRequest with entity and configurations to be saved.
54+
* @param <T> Type of Entity object.
55+
*/
56+
<T> T update(UpdateItemEnhancedRequest<T> request);
57+
4858
/**
4959
* Deletes a record for a given Key.
5060
*

spring-cloud-aws-dynamodb/src/main/java/io/awspring/cloud/dynamodb/DynamoDbTemplate.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,19 @@
2424
import software.amazon.awssdk.enhanced.dynamodb.model.PageIterable;
2525
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;
2626
import software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest;
27+
import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedRequest;
2728

2829
/**
2930
* Default implementation of {@link DynamoDbOperations}.
3031
*
3132
* @author Matej Nedic
3233
* @author Arun Patra
3334
* @author Maciej Walkowiak
35+
* @author Marcus Voltolim
3436
* @since 3.0
3537
*/
3638
public class DynamoDbTemplate implements DynamoDbOperations {
39+
3740
private final DynamoDbEnhancedClient dynamoDbEnhancedClient;
3841
private final DynamoDbTableSchemaResolver dynamoDbTableSchemaResolver;
3942
private final DynamoDbTableNameResolver tableNameResolver;
@@ -66,6 +69,12 @@ public <T> T update(T entity) {
6669
return prepareTable(entity).updateItem(entity);
6770
}
6871

72+
@Override
73+
public <T> T update(UpdateItemEnhancedRequest<T> request) {
74+
Assert.notNull(request, "updateItemEnhancedRequest is required");
75+
return prepareTable(request.item()).updateItem(request);
76+
}
77+
6978
public <T> T delete(Key key, Class<T> clazz) {
7079
Assert.notNull(key, "key is required");
7180
Assert.notNull(clazz, "clazz is required");

spring-cloud-aws-dynamodb/src/test/java/io/awspring/cloud/dynamodb/DynamoDbTemplateIntegrationTest.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
import java.util.ArrayList;
2121
import java.util.List;
2222
import java.util.UUID;
23+
import java.util.stream.Stream;
2324
import org.junit.jupiter.api.BeforeAll;
2425
import org.junit.jupiter.params.ParameterizedTest;
2526
import org.junit.jupiter.params.provider.Arguments;
2627
import org.junit.jupiter.params.provider.MethodSource;
2728
import org.springframework.lang.Nullable;
2829
import org.springframework.util.StringUtils;
2930
import software.amazon.awssdk.enhanced.dynamodb.*;
31+
import software.amazon.awssdk.enhanced.dynamodb.model.*;
3032
import software.amazon.awssdk.enhanced.dynamodb.model.PageIterable;
3133
import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
3234
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;
@@ -40,6 +42,7 @@
4042
* @author Matej Nedic
4143
* @author Arun Patra
4244
* @author Artem Bilan
45+
* @author Marcus Voltolim
4346
*/
4447
public class DynamoDbTemplateIntegrationTest implements LocalstackContainerTest {
4548

@@ -51,7 +54,7 @@ public class DynamoDbTemplateIntegrationTest implements LocalstackContainerTest
5154
private static final String nameOfGSPK = "gsPk";
5255

5356
@BeforeAll
54-
public static void createTable() {
57+
static void createTable() {
5558
DynamoDbClient dynamoDbClient = LocalstackContainerTest.dynamoDbClient();
5659
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build();
5760

@@ -96,12 +99,36 @@ void dynamoDbTemplate_saveUpdateAndRead_entitySuccessful(DynamoDbTable<PersonEnt
9699
PersonEntity personEntity = new PersonEntity(UUID.randomUUID(), "foo", "bar");
97100
dynamoDbTemplate.save(personEntity);
98101

102+
personEntity.setName(null);
99103
personEntity.setLastName("xxx");
100104
dynamoDbTemplate.update(personEntity);
101105

102-
PersonEntity personEntity1 = dynamoDbTemplate
103-
.load(Key.builder().partitionValue(personEntity.getUuid().toString()).build(), PersonEntity.class);
104-
assertThat(personEntity1).isEqualTo(personEntity);
106+
Key key = Key.builder().partitionValue(personEntity.getUuid().toString()).build();
107+
108+
assertThat(dynamoDbTemplate.load(key, PersonEntity.class))
109+
.extracting(PersonEntity::getName, PersonEntity::getLastName).containsExactly(null, "xxx");
110+
111+
// clean up
112+
cleanUp(dynamoDbTable, personEntity.getUuid());
113+
}
114+
115+
@ParameterizedTest
116+
@MethodSource("argumentSource")
117+
void dynamoDbTemplate_saveUpdateIgnoreNullAndRead_entitySuccessful(DynamoDbTable<PersonEntity> dynamoDbTable,
118+
DynamoDbTemplate dynamoDbTemplate) {
119+
PersonEntity personEntity = new PersonEntity(UUID.randomUUID(), "foo", "bar");
120+
dynamoDbTemplate.save(personEntity);
121+
122+
personEntity.setName(null);
123+
personEntity.setLastName("xxx");
124+
UpdateItemEnhancedRequest<PersonEntity> request = UpdateItemEnhancedRequest.builder(PersonEntity.class)
125+
.item(personEntity).ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY).build();
126+
dynamoDbTemplate.update(request);
127+
128+
Key key = Key.builder().partitionValue(personEntity.getUuid().toString()).build();
129+
130+
assertThat(dynamoDbTemplate.load(key, PersonEntity.class))
131+
.extracting(PersonEntity::getName, PersonEntity::getLastName).containsExactly("foo", "xxx");
105132

106133
// clean up
107134
cleanUp(dynamoDbTable, personEntity.getUuid());
@@ -299,16 +326,16 @@ public static void cleanUp(DynamoDbTable<PersonEntity> dynamoDbTable, UUID uuid)
299326
dynamoDbTable.deleteItem(Key.builder().partitionValue(uuid.toString()).build());
300327
}
301328

302-
private static java.util.stream.Stream<Arguments> argumentSource() {
303-
return java.util.stream.Stream.of(Arguments.of(dynamoDbTable, dynamoDbTemplate),
329+
private static Stream<Arguments> argumentSource() {
330+
return Stream.of(Arguments.of(dynamoDbTable, dynamoDbTemplate),
304331
Arguments.of(prefixedDynamoDbTable, prefixedDynamoDbTemplate));
305332
}
306333

307334
private static void describeAndCreateTable(DynamoDbClient dynamoDbClient, @Nullable String tablePrefix) {
308-
ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
335+
ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<>();
309336
attributeDefinitions.add(AttributeDefinition.builder().attributeName("uuid").attributeType("S").build());
310337
attributeDefinitions.add(AttributeDefinition.builder().attributeName(nameOfGSPK).attributeType("S").build());
311-
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
338+
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<>();
312339
tableKeySchema.add(KeySchemaElement.builder().attributeName("uuid").keyType(KeyType.HASH).build());
313340
List<KeySchemaElement> indexKeySchema = new ArrayList<>();
314341
indexKeySchema.add(KeySchemaElement.builder().attributeName(nameOfGSPK).keyType(KeyType.HASH).build());
@@ -332,4 +359,5 @@ private static void describeAndCreateTable(DynamoDbClient dynamoDbClient, @Nulla
332359
// table already exists, do nothing
333360
}
334361
}
362+
335363
}

0 commit comments

Comments
 (0)