【问题标题】:On Spring, how to query DynamoDB table using JPA and a composite key (Partition Key and Sort Key)?在 Spring 上,如何使用 JPA 和复合键(分区键和排序键)查询 DynamoDB 表?
【发布时间】:2020-04-29 20:30:05
【问题描述】:

我有一个使用 JPA 和 Spring Data DynamoDB 设置的 Spring 项目。它工作正常。我可以通过 Partition Key 和 Sort key(称为DynamoDBHashKeyDynamoDBRangeKey)读取DynamoDB表中的项目。

我的问题是我的存储库的设置方式,使用queryscan操作读取表,而不是get-item操作,应该更有效。

这是我的实体:

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@DynamoDBTable(tableName = "my-entity-table")
public class MyEntity {

    @Id
    @DynamoDBHashKey 
    @DynamoDBAttribute(attributeName = "partition_key")
    private String partitionKey;

    @Id
    @DynamoDBRangeKey
    @DynamoDBAttribute(attributeName = "sort_key")
    private String sortKey;

    ...
}

这是我的存储库:

import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@EnableScan
@Repository
public interface MyEntityRepository extends CrudRepository<MyEntity, String> {
    List<MyEntity> findByPartitionKeyAndSortKey(String partitionKey, String sortKey);
}

当我的表同时具有分区键和排序键时,如何配置我的实体和存储库以使用 get-item 操作从表中读取项目?

【问题讨论】:

    标签: java spring jpa spring-data-jpa amazon-dynamodb


    【解决方案1】:

    做了一些研究后,我偶然发现了这两篇文章:

    1. Composite Primary Keys Kotlin Example
    2. Spring Data JPA with a Hash & Range Key DynamoDB Table

    第一个解释了如何在 Kotlin 中做我想做的事。不错,但它并不是我想要的。

    第二个完美命中目标,基本上就是说我需要为我的实体对象创建一个主键对象,像这样:

    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDocument;
    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIgnore;
    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import org.springframework.data.annotation.Id;
    
    @Getter
    @Setter
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @DynamoDBTable(tableName = "my-entity-table")
    public class MyEntity {
    
        @Id
        @DynamoDBIgnore
        private PrimaryKey primaryKey;
    
        ...
    
        @DynamoDBHashKey
        @DynamoDBAttribute(attributeName = "partition_key")
        public String getPartitionKey() {
            return primaryKey != null ? primaryKey.getPartitionKey() : null;
        }
    
        public void setPartitionKey(final String partitionKey) {
            if (primaryKey == null) {
                primaryKey = new PrimaryKey();
            }
            primaryKey.setPartitionKey(partitionKey);
        }
    
        @DynamoDBRangeKey
        @DynamoDBAttribute(attributeName = "sort_key")
        public String getSortKey() {
            return primaryKey != null ? primaryKey.getSortKey() : null;
        }
    
        public void setSortKey(final String sortKey) {
            if (primaryKey == null) {
                primaryKey = new PrimaryKey();
            }
            primaryKey.setSortKey(sortKey);
        }
    
        @Getter
        @Setter
        @NoArgsConstructor
        @AllArgsConstructor
        @DynamoDBDocument
        public static class PrimaryKey {
            @DynamoDBHashKey 
            @DynamoDBAttribute(attributeName = "partition_key")
            private String partitionKey;
    
            @DynamoDBRangeKey
            @DynamoDBAttribute(attributeName = "sort_key")
            private String sortKey;
        }
    }
    

    然后,我不需要在我的存储库类上创建任何自定义查询方法:

    @EnableScan
    @Repository
    public interface MyEntityRepository extends 
            CrudRepository<MyEntity, MyEntity.PrimaryKey> {
    
    }
    

    然后,只需使用 JPA 的 CrudRepository 方法来获取项目,如下所示:

    final MyEntity.PrimaryKey myEntityPK 
        = new MyEntity.PrimaryKey("partitionKey", "sortKey");
    
    final MyEntity myEntity = myEntityRepository.findById(myEntityPK)
        .orElseThrow(() -> ... );
    
    

    要验证它实际上使用的是get-item 操作而不是scanquery 操作,可以在以下类上放置几个断点(截至spring-data-dynamodb-5.1.0):

    • org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate
    • org.socialsignin.spring.data.dynamodb.repository.support.SimpleDynamoDBCrudRepository

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-19
      • 1970-01-01
      • 2022-06-12
      • 2021-05-30
      • 2017-07-18
      • 1970-01-01
      相关资源
      最近更新 更多