derjust / spring-data-dynamodb

This module deals with enhanced support for a data access layer built on AWS DynamoDB.
https://derjust.github.io/spring-data-dynamodb/
Apache License 2.0
403 stars 141 forks source link

DeleteByIdAndAttr is not working #204

Open rmckinnon opened 6 years ago

rmckinnon commented 6 years ago

Expected Behavior

When calling the repository.deleteByIdAndSomeAttribute doesn't work when the SomeAttribute is the primary sort key.

Actual Behavior

A org.socialsignin.spring.data.dynamodb.exception.BatchDeleteException is thrown with the following stacktrace:

org.socialsignin.spring.data.dynamodb.exception.BatchDeleteException: Processing of entities failed!; nested exception is com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The provided key element does not match the schema (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 8GO7K4Q4AV4OA14MF45MQKPEDFVV4KQNSO5AEMVJF66Q9ASUAAJG)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_181]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_181]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_181]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_181]
    at org.socialsignin.spring.data.dynamodb.utils.ExceptionHandler.repackageToException(ExceptionHandler.java:40) ~[spring-data-dynamodb-5.0.3.jar:5.0.3]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery$DeleteExecution.execute(AbstractDynamoDBQuery.java:268) ~[spring-data-dynamodb-5.0.3.jar:5.0.3]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.execute(AbstractDynamoDBQuery.java:311) ~[spring-data-dynamodb-5.0.3.jar:5.0.3]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:590) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
....

Steps to Reproduce the Problem

  1. Create DynamoDB with a primary sort key defined. In my case the primary partition key is "id" and the primary sort key is "childId"
  2. Create some records in DynmoDB
  3. Using the String Data conventions extend the repository to delete by id and childId

Excerpt:

@EnableScan
public interface ProgramCrudRepository extends CrudRepository<Program, String> {
    void deleteByIdAndChildId(String id, String childId);
}
  1. Invoke the deleteByIdAndChildId

Specifications

derjust commented 6 years ago

I just created a test case for the described scenario: https://github.com/derjust/spring-data-dynamodb/pull/208/files#diff-dcdb5f59762ba17e758ce60997071885R196

If I understand correctly, the given situation is that id is the Hash key and childId is the Range key. As with the entity model itself, DynamoDB's structure and the way spring-data expects doesn't perfectly align: The deleteById (Id as the conceptual thing represented by two fields on the DynamoDB side but as a distinct entity class on the spring-data side) on the repository must be used - as per the referenced example.

Otherwise the childId is considered a regular attribute - which is not the case as it marked as part of the (conceptual) id

derjust commented 6 years ago

Updated the wiki.