1. 概述

在这篇文章中,我们将深入探讨如何在Spring Boot应用中集成DynamoDB。我们将通过一个实践性的示例项目来演示。

我们将展示如何配置应用使用Spring Data连接本地的DynamoDB实例,并创建一个数据模型、仓库类,以及使用集成测试进行实际数据库操作。

2. DynamoDB

DynamoDB是AWS上的一款全托管的NoSQL数据库,类似于Cassandra或MongoDB。它提供了快速、一致且可预测的性能,并且可以大规模扩展。

更多关于DynamoDB的信息可以在AWS文档中找到。

为了避免运行实时实例的成本,我们将安装一个本地DynamoDB实例

对于开发而言,本地运行DynamoDB比在AWS上更为合理;本地实例将作为可执行的JAR文件运行。

有关如何在本地运行DynamoDB的说明,请参阅此处

3. Maven依赖

首先,让我们添加必要的依赖,以便使用Spring Data与DynamoDB一起工作:

<dependencies>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-commons</artifactId>
        <version>2.7.18</version>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-dynamodb</artifactId>
        <version>1.12.714</version>
    </dependency>
    <dependency>
        <groupId>com.github.derjust</groupId>
        <artifactId>spring-data-dynamodb</artifactId>
        <version>5.1.0</version>
    </dependency>
</dependencies>

我们需要获取Spring Data Commons的最新版本([这里](https://mvnrepository.com/artifact/org.springframework.data/spring-data-commons))、AWS Java SDK for Amazon DynamoDB([这里](https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-dynamodb))和Spring Data DynamoDB(这里)的最新版本。

4. 配置

接下来,在application.properties文件中定义以下属性:

amazon.dynamodb.endpoint=http://localhost:8000/
amazon.aws.accesskey=key
amazon.aws.secretkey=key2

上面列出的访问密钥和秘密密钥仅为本地配置的随机值。当连接本地DynamoDB实例时,这些字段需要填充一些值,但在验证身份时并不需要。

这些属性将在Spring配置中动态地从application.properties文件中读取:

@Configuration
@EnableDynamoDBRepositories
  (basePackages = "com.baeldung.spring.data.dynamodb.repositories")
public class DynamoDBConfig {

    @Value("${amazon.dynamodb.endpoint}")
    private String amazonDynamoDBEndpoint;

    @Value("${amazon.aws.accesskey}")
    private String amazonAWSAccessKey;

    @Value("${amazon.aws.secretkey}")
    private String amazonAWSSecretKey;

    @Bean
    public AmazonDynamoDB amazonDynamoDB() {
        AmazonDynamoDB amazonDynamoDB 
          = new AmazonDynamoDBClient(amazonAWSCredentials());
        
        if (!StringUtils.isEmpty(amazonDynamoDBEndpoint)) {
            amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint);
        }
        
        return amazonDynamoDB;
    }

    @Bean
    public AWSCredentials amazonAWSCredentials() {
        return new BasicAWSCredentials(
          amazonAWSAccessKey, amazonAWSSecretKey);
    }
}

5. 数据模型

现在,我们创建一个POJO模型来表示存储在DynamoDB中的数据。

这个POJO将使用类似于Hibernate的注解来定义表名、属性、键和其他表的特性。

5.1. 数据模型属性

名为ProductInfo的类代表一个包含3个属性的表:

  1. ID
  2. MSRP
  3. 成本

5.2. Java数据模型类

在数据模型文件夹中创建一个名为ProductInfo.java的文件:

@DynamoDBTable(tableName = "ProductInfo")
public class ProductInfo {
    private String id;
    private String msrp;
    private String cost;

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    public String getId() {
        return id;
    }

    @DynamoDBAttribute
    public String getMsrp() {
        return msrp;
    }

    @DynamoDBAttribute
    public String getCost() {
        return cost;
    }

    // standard setters/constructors
}

6. CRUD仓库

接下来,我们需要创建一个ProductRepository接口,以定义我们想要构建的CRUD功能。用于从DynamoDB读取和持久化数据的仓库将实现这个接口:

@EnableScan
public interface ProductInfoRepository extends 
  CrudRepository<ProductInfo, String> {
    
    Optional<ProductInfo> findById(String id);
}

7. 集成测试

然后,让我们创建一个集成测试,以确保我们可以成功连接到本地的DynamoDB实例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
@ActiveProfiles("local")
@TestPropertySource(properties = { 
  "amazon.dynamodb.endpoint=http://localhost:8000/", 
  "amazon.aws.accesskey=test1", 
  "amazon.aws.secretkey=test231" })
public class ProductInfoRepositoryIntegrationTest {

    private DynamoDBMapper dynamoDBMapper;

    @Autowired
    private AmazonDynamoDB amazonDynamoDB;

    @Autowired
    ProductInfoRepository repository;

    private static final String EXPECTED_COST = "20";
    private static final String EXPECTED_PRICE = "50";

    @Before
    public void setup() throws Exception {
        dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
        
        CreateTableRequest tableRequest = dynamoDBMapper
          .generateCreateTableRequest(ProductInfo.class);
        tableRequest.setProvisionedThroughput(
          new ProvisionedThroughput(1L, 1L));
        amazonDynamoDB.createTable(tableRequest);
        
        //...

        dynamoDBMapper.batchDelete(
          (List<ProductInfo>)repository.findAll());
    }

    @Test
    public void givenItemWithExpectedCost_whenRunFindAll_thenItemIsFound() { 
        ProductInfo productInfo = new ProductInfo(EXPECTED_COST, EXPECTED_PRICE);
        repository.save(productInfo); 
        List<ProductInfo> result = (List<ProductInfo>) repository.findAll();

        assertThat(result.size(), is(greaterThan(0)));
        assertThat(result.get(0).getCost(), is(equalTo(EXPECTED_COST))); 
    }
}

8. 总结

至此,我们已经完成了连接DynamoDB到Spring Boot应用的过程。

当然,在本地测试完成后,我们应能够无缝地使用AWS上的实时DynamoDB实例,并仅需少量配置更改即可运行部署代码。

如往常一样,本文中的示例项目可在GitHub上的样本项目中找到。