在Spring上,如何使用JPA和复合键(分区键和排序键)查询DynamoDB表?

时间:2019-08-07 03:20:41

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

我有一个使用JPA和Spring Data DynamoDB设置的Spring项目。一切正常。我可以通过使用分区键和排序键(分别称为DynamoDBHashKeyDynamoDBRangeKey)读取DynamoDB表中的项目。

我的问题是,建立存储库的方式是使用queryscan操作而不是get-item操作读取表,这应该更有效。 / p>

这是我的实体:

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操作从表中读取项目?

1 个答案:

答案 0 :(得分:0)

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

  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 SponsorProvider.PrimaryKey("partitionKey", "sortKey");

final MyEntity myEntity = myEntityRepository.findById(myEntityPK)
    .orElseThrow(() -> ... );

要验证它实际上是在使用get-item操作而不是scanquery操作,可以在以下类上放置几个断点(自{{1 }}):

  • spring-data-dynamodb-5.1.0
  • org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate