当前位置: 首页 > 知识库问答 >
问题:

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

费承载
2023-03-14

我有一个用JPA和Spring Data DynamoDB建立的Spring项目。它工作正常。我可以通过分区键和排序键(称为DynamoDBHashKey和DynamoDBRangeKey)读取DynamoDB表中的项。

我的问题是,我的存储库的设置方式是使用查询和扫描操作来读取表,而不是使用获取项目操作,这应该会更高效。

这是我的实体:

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个答案

梁华皓
2023-03-14

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

  1. 复合主键Kotlin示例
  2. 带哈希的Spring数据JPA

第一个解释了如何在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操作而不是扫描查询操作,可以在以下类上放置几个断点(截至spring-data-Dynamodb-5.1.0):

  • org.socialsignin.spring.data.dynamodb.core.DynamoDBTemboard
  • org.socialsignin.spring.data.dynamodb.repository.support.SimpleDynamoDBCrudRepository
 类似资料:
  • 我试图查询具有分区键和排序键的表(但是分区键和排序键是1:1,我只想使用分区键[仅返回一项]进行查询)。 这是我尝试过的代码,但没有成功(testId是分区键名,1234567890是字符串形式的分区键值);你们都知道我可以只使用分区键进行查询的方法吗?记住,由于分区键和排序键是1:1,所以只会返回一个项?提前非常感谢您。[这是我的第一篇堆栈溢出帖子-很抱歉,如果我用词不当,我很乐意回答关于我的措

  • 我试图使用batchGetItem从表中返回多个项的属性,但似乎它只适用于分区键和范围键的组合,但是如果我只想通过主键识别请求的项,该怎么办?唯一的方法是创建不带范围键的表吗? 根据官方留档: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html 如果表有一个复合主键(分

  • 假设我有一个名为“student_course”的Dynamo DB表。我想存储每个学生在大学学习的课程。一个学生可以一次学习多个课程,一个课程可以一次有多个学生。所以基本上它是一个多映射。 我的数据访问模式只有一个用例- 一次获取一个学生和一门课程的记录,即获取每个学生ID和CourseId组合的数据。它保证对于学生ID和课程ID组合,只有一条记录可用。 为了实现这一点,我可以通过以下两种方式存

  • 我是DynamoDB的新手,想知道我们如何通过在JAVA中使用ONLY分区键来查询DynamoDB中的表 我有一个名为“ervive pdi data invalid qa”的表,其模式是: 分区键为SubmissionId 排序键是id。 城市(属性) 错误(属性) 这张桌子看起来像这样:桌子 我想通过使用(software.amazon.awssdk)新版本的AWS SDK DynamoDB类

  • 我们大量使用cassandra wide rows来存储每个用户的时间序列,因为它们非常适合那个用例。假设我们有一个表: 如果时间戳上的冲突可能发生(相同的用户可以用相同的时间戳发出两个不同的事件)。假设我们对所有事件都有一个顺序(每个事件都有一个序列int),那么调整这个模式来解决这个问题的最佳方法是什么。 我将无法执行-cassandra不允许这样做。

  • 与主键、复合键和候选键相比,dynamodb中的分区键和排序键是什么?