Reputation: 1317
I have a DynamoDB table with the following key [customerid (HASH), sku (RANGE)].
I'm trying to query by customerid only. I'm currently getting this error:
Caused by: java.lang.IllegalStateException: You have defined query method in the repository but you don't have any query lookup strategy defined. The infrastructure apparently does not support query methods!
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:545) ~[spring-data-commons-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:324) ~[spring-data-commons-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297) ~[spring-data-commons-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:211) ~[spring-data-commons-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.data.util.Lazy.get(Lazy.java:94) ~[spring-data-commons-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300) ~[spring-data-commons-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
... 30 common frames omitted
I've added the queryLookupStrategy to my application in the hopes it worked. Tried the several values, but the message remains.
@SpringBootApplication
@EnableDynamoDBRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)
public class ProductItemApplication {
public static void main(String[] args) {
SpringApplication.run(ProductItemApplication.class, args);
}
}
Is that possible? Or is it a limitation of Dynamo? Since Cassandra can easily do this, I'm assuming Dynamo would be able to do it too, but may be wrong.
Would I need to define an index with only customerid to query this? If so, what's the best way to do that in code with spring-data?
Or is this a limitation of spring data with dynamo, and to achieve this I'd need to use the dynamo client explicitly rather than spring data?
My repository is defined as such:
interface CustomerItemRepository extends CrudRepository<CustomerItem, CustomerItemId> {
List<CustomerItem> findByCustomerId(String customerId);
}
And my key is:
@NoArgsConstructor
@AllArgsConstructor
public class CustomerItemId {
private String customerId;
private String sku;
@DynamoDBHashKey(attributeName = "customerId")
public String getCustomerId() {
return customerId;
}
@SuppressWarnings("unused")
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
@DynamoDBRangeKey(attributeName = "sku")
public String getSku() {
return sku;
}
@SuppressWarnings("unused")
public void setSku(String sku) {
this.sku = sku;
}
}
Finally, my item is:
@DynamoDBTable(tableName = "CustomerItem")
@NoArgsConstructor
public class CustomerItem {
@Id
private CustomerItemId id;
//... a few other non key fields...
CustomerItem(String customerId, String sku) {
this.id = new CustomerItemId(customerId, sku);
}
@DynamoDBHashKey(attributeName = "customerId")
public String getCustomerId() {
return id.getCustomerId();
}
@DynamoDBRangeKey(attributeName = "sku")
public String getSku() {
return id.getSku();
}
public void setCustomerId(String customerId) {
this.id = new CustomerItemId(customerId, id != null ? id.getSku() : null);
}
public void setSku(String sku) {
this.id = new CustomerItemId(id != null ? id.getCustomerId() : null, sku);
}
}
What's the most elegant way to solve this? Dynamo seemed the right tech to store this kind of simple data cheaply, but now I'm thinking I may be better off using something else.
Upvotes: 3
Views: 4255
Reputation: 14799
I know this does not address your question, but for a Java project I would use DynamoDBMapper for object persistence, not Spring. It provides a really clean way to map your plain objects into DynamoDB and is provided and supported by AWS. I've used it a lot and DynamoDBMapper is excellent.
Upvotes: 3