【问题标题】:How to query DynamoDB table by hash using Spring Data如何使用 Spring Data 通过哈希查询 DynamoDB 表
【发布时间】:2019-01-07 22:20:32
【问题描述】:

我有一个 DynamoDB 表,其中包含以下键 [customerid (HASH), sku (RANGE)]。

我正在尝试仅通过 customerid 进行查询。我目前收到此错误:

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

我已将 queryLookupStrategy 添加到我的应用程序中,希望它能正常工作。尝试了几个值,但消息仍然存在。

@SpringBootApplication
@EnableDynamoDBRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)
public class ProductItemApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductItemApplication.class, args);
    }
}

这可能吗?还是 Dynamo 的限制?由于 Cassandra 可以轻松做到这一点,我假设 Dynamo 也可以做到这一点,但可能是错误的。

我需要定义一个只有 customerid 的索引来查询吗?如果是这样,使用 spring-data 在代码中执行此操作的最佳方法是什么?

或者这是 dynamo 对 spring 数据的限制,为了实现这一点,我需要显式使用 dynamo 客户端而不是 spring 数据?

我的存储库是这样定义的:

interface CustomerItemRepository extends CrudRepository<CustomerItem, CustomerItemId> {
    List<CustomerItem> findByCustomerId(String customerId);
}

我的关键是:

@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;
    }
}

最后,我的项目是:

    @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);
        }
    }

解决这个问题最优雅的方法是什么? Dynamo 似乎是廉价存储此类简单数据的合适技术,但现在我想我最好还是使用其他东西。

【问题讨论】:

  • 我知道这并不能解决您的问题,但对于 Java 项目,我会使用 DynamoDBMapper 进行对象持久性,而不是 Spring。 DynamoDBMapper 非常棒。
  • 我实际上尝试改用 DynamoDBMapper,而且它工作起来很轻松,所以我会改用它。谢谢!如果您想将其作为答案,我很乐意接受。
  • 谢谢,很高兴你发现它有用。我已经添加了答案。
  • derjust/spring-data-dynamodb 实现实际上使用了DynamoDbMapper,这就是在您的实体上使用 AWS 注释的原因。肯定可以仅通过散列键进行查询的——我们在很多地方都使用这个库来做到这一点。如果你能提供一个完整的示例项目,包含确切的版本和所有依赖项等,我可能会找出不正确的地方。

标签: java spring-data amazon-dynamodb


【解决方案1】:

我知道这不能解决您的问题,但对于 Java 项目,我会使用 DynamoDBMapper 来进行对象持久性,而不是 Spring。它提供了一种非常简洁的方式来将您的普通对象映射到 DynamoDB,并且由 AWS 提供和支持。我用过很多次,DynamoDBMapper 非常棒。

【讨论】:

  • 是的,它没有 Spring 在仅通过哈希查询时似乎有的“错误”(?),并且编写一个通用类来处理 dynamodb 访问几乎提供了与 Spring 相同的抽象级别,所以绝对适合我。只是强迫你再写几个测试,但我可以忍受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 1970-01-01
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多