Search code examples
amazon-dynamodbaws-sdkdynamodb-mapper

DynamoDB Mapper SaveExpression not throwing ConditionalCheckFailedException when record already exists


I have a DynamoDB table which has 3 attributes(partition key - id, sortkey - orderId, info). I am trying to write into DynamoDB if the record does not exist(either the partition key or the sort key) already. My code snippet as below

public void saveRecord(@NonNull Payload payload) {

        final String id = payload.getId();
        final String orderId = payload.getOrderId();

            Map<String, ExpectedAttributeValue> expectedAttributes =
                    ImmutableMap.<String, ExpectedAttributeValue>builder()
                            .put(id, new ExpectedAttributeValue().withExists(false))
                            .put(orderId, new ExpectedAttributeValue().withExists(false))
                            .build();

            DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression()
                    .withExpected(expectedAttributes)
                    .withConditionalOperator(ConditionalOperator.OR);

            ObjectToSave objectToSave = ObjectToSave.builder()
                    .id(id)
                    .sortKey(orderId)
                    .info(payload.getInfo())
                    .build();

            try {
            dynamoDBMapper.save(objectToSave, saveExpression);
            log.info("write successful");
        } catch (ConditionalCheckFailedException e) {
            log.error("Record already exists id:{}, sortKey: {}", id, orderId);
        }
    }

My understanding is whenever I receive a record that already exists in the table, the above code should log the error statement. But It's not happening like that. What am I missing here or doing wrong?


Solution

  • This is because you pass in the AttributeValue of the partition and sort key, rather than the AttributeNames:

    public void saveRecord(@NonNull Payload payload) {
    
            final String id = payload.getId();
            final String orderId = payload.getOrderId();
    
                Map<String, ExpectedAttributeValue> expectedAttributes =
                        ImmutableMap.<String, ExpectedAttributeValue>builder()
                                .put("id", new ExpectedAttributeValue().withExists(false))
                                .put("orderId", new ExpectedAttributeValue().withExists(false))
                                .build();
    
                DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression()
                        .withExpected(expectedAttributes)
                        .withConditionalOperator(ConditionalOperator.OR);
    
                ObjectToSave objectToSave = ObjectToSave.builder()
                        .id(id)
                        .sortKey(orderId)
                        .info(payload.getInfo())
                        .build();
    
                try {
                dynamoDBMapper.save(objectToSave, saveExpression);
                log.info("write successful");
            } catch (ConditionalCheckFailedException e) {
                log.error("Record already exists id:{}, sortKey: {}", id, orderId);
            }
        }