本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
DynamoDB 表中的映射项目
DynamoDB 增强版客户端是一个高级库,是其中的一部分Amazon SDK for Java 2.x。它提供了一种将客户端类映射到 DynamoDB 表执行的直接方法。您可以在代码中定义表与其相应模型类之间的关系。定义了这些关系后,您可以直观地对 DynamoDB 中的表执行各种创建、读取、更新或删除 (CRUD) 操作。
要开始在项目中使用增强型客户端,除了在编译文件dynamodb-enhanced
中添加对 Mavendynamodb
工件的依赖关系,如以下示例之一所示。
创建目标DynamoDbEnhancedClient
该DynamoDbEnhancedClient
实例用于处理 DynamoDB 表和映射类。您DynamoDbEnhancedClient
从现有DynamoDbClient
对象创建,如下面的示例所示。
DynamoDbClient ddb = DynamoDbClient.builder() .region(Region.US_EAST_1) .build(); DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(ddb) .build(); // Use the enhancedClient.
生成TableSchema
当您使用增强版客户端的映射功能时,您采取的第一步是生成TableSchema
。您可以通过两种方式来进行。
使用带注释的 Java Bean
SDK for Java 2.x 包含一组注解TableSchema
用于将类映射到表的注释。
首先创建一个 Java 数据类,该数据类包括默认的公共构造函数以及该类中每个属性的获取者和设置器的标准化名称。包括一个类级别注释以指示它是 DynamoDbBean
,并且至少在 getter 或 setter 上包含对于表记录主键的 DynamoDbPartitionKey
注释。
以下Customer
类显示了这些注解,这些注解会将类定义链接到 DynamoDB 表。
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ package com.example.dynamodb; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; import java.time.Instant; /** * This class is used by the Enhanced Client examples. */ @DynamoDbBean public class Customer { private String id; private String name; private String email; private Instant regDate; @DynamoDbPartitionKey public String getId() { return this.id; } public void setId(String id) { this.id = id; } public String getCustName() { return this.name; } public void setCustName(String name) { this.name = name; } @DynamoDbSortKey public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } public Instant getRegistrationDate() { return regDate; } public void setRegistrationDate(Instant registrationDate) { this.regDate = registrationDate; } @Override public String toString() { return "Customer [id=" + id + ", name=" + name + ", email=" + email + ", regDate=" + regDate + "]"; } }
创建了带注释的 Java Bean 后,用它来创建TableSchema
,如下面的代码段所示。
TableSchema<Customer> customerTableSchema = TableSchema.fromBean(Customer.class);
使用生成器
如果你想跳过稍微昂贵的 bean 自省来获得更快的解决方案,你可以改为直接声明你的架构,让编译器来完成繁重的工作。如果你这样做,你的类不需要遵循 Bean 命名标准,也不需要对其进行注释。以下示例使用生成器,等同于 bean 示例。
TableSchema<Customer> customerTableSchema = TableSchema.builder(Customer.class) .newItemSupplier(Customer::new) .addAttribute(String.class, a -> a.name("id") .getter(Customer::getId) .setter(Customer::setId) .tags(primaryPartitionKey())) .addAttribute(Integer.class, a -> a.name("email") .getter(Customer::getEmail) .setter(Customer::setEmail) .tags(primarySortKey())) .addAttribute(String.class, a -> a.name("name") .getter(Customer::getCustName) .setter(Customer::setCustName)) .addAttribute(Instant.class, a -> a.name("registrationDate") .getter(Customer::getRegistrationDate) .setter(Customer::setRegistrationDate)) .build();
使用增强型客户端创建表
以下示例展示了如何从Customer
Java Data Bean 类创建 DynamoDB 表。
要创建DynamoDbTable
TableSchema
给增强型客户端table()
的方法。此示例创建了一个名为Customer
(与类名相同)的表,但表名可以是其他名称。无论您为该表命名什么,都必须在其他应用程序中使用此名称才能使用该表。每当您创建另一个DynamoDbTable
对象时,都要为该table()
方法提供此名称。
传递给该createTable
方法的 lambda 参数允许您自定义表builder
该示例还使用了DynamoDbWaiter
. 由于创建表需要一点时间,因此使用服务员可以避免在使用表之前编写逻辑来轮询 DynamoDB 服务以查看该表是否存在。
导入
import com.example.dynamodb.Customer; import software.amazon.awssdk.core.internal.waiters.ResponseOrException; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
代码
public class EnhancedCreateTable { public static void createTable(DynamoDbEnhancedClient enhancedClient) { // Create a DynamoDbTable object DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); // Create the table customerTable.createTable(builder -> builder .provisionedThroughput(b -> b .readCapacityUnits(10L) .writeCapacityUnits(10L) .build()) ); System.out.println("Waiting for table creation..."); try (DynamoDbWaiter waiter = DynamoDbWaiter.create()) { // DynamoDbWaiter is Autocloseable ResponseOrException<DescribeTableResponse> response = waiter .waitUntilTableExists(builder -> builder.tableName("Customer").build()) .matched(); DescribeTableResponse tableDescription = response.response().orElseThrow( () -> new RuntimeException("Customer table was not created.")); // The actual error can be inspected in response.exception() System.out.println(tableDescription.table().tableName() + " was created."); } } }
请参阅上的完整示例
检索(获取)表中的项目
要从 DynamoDB 表中获取项目,请创建一个DynamoDbTable对象并调getItem()
用GetItemEnhancedRequest对象。作为传入GetItemEnhancedRequest
对象的替代方法,您可以利用 lambda 表达式和 SDK 的生成器模式。在下面的示例中,该getItem()
方法采用Consumer<GetItemEnhancedRequest.Builder>
最终为您创建 GetItemEnhancedRequest
对象。
为了便于解释,该示例使用了完整的 lambda 语法(GetItemEnhancedRequest.Builder requestBuilder) ->
requestBuilder.key(key)
,但诸如之类的更简单的表达式也rb →
rb.key(key)
可以。
以下代码段演示了使用增强客户端从 DynamoDB 表中的项目获取信息。
导入
import com.example.dynamodb.Customer; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedRequest; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
代码
public static String getItem(DynamoDbEnhancedClient enhancedClient) { Customer result = null; try { DynamoDbTable<Customer> table = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); Key key = Key.builder() .partitionValue("id101").sortValue("tred@noserver.com") .build(); // Get the item by using the key. result = table.getItem( (GetItemEnhancedRequest.Builder requestBuilder) -> requestBuilder.key(key)); System.out.println("******* The description value is " + result.getCustName()); } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } return result.getCustName(); }
请参阅上的完整示例
向表添加新项目
要使用增强型客户端将新项目插入表中,需要创建一个带有注解的 Java Bean 数据类的实例@DynamoDbBean
。使用 Java Bean 实例的设置器添加要插入的数据。使用putItem()
方法执行DynamoDbTable
插入。
以下示例显示了添加到Customer
表执行的一个项目。
导入
import com.example.dynamodb.Customer; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset;
代码
public static void putRecord(DynamoDbEnhancedClient enhancedClient) { try { DynamoDbTable<Customer> custTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); // Create an Instant value. LocalDate localDate = LocalDate.parse("2020-04-07"); LocalDateTime localDateTime = localDate.atStartOfDay(); Instant instant = localDateTime.toInstant(ZoneOffset.UTC); // Populate the Table. Customer custRecord = new Customer(); custRecord.setCustName("Tom red"); custRecord.setId("id101"); custRecord.setEmail("tred@noserver.com"); custRecord.setRegistrationDate(instant) ; // Put the customer data into an Amazon DynamoDB table. custTable.putItem(custRecord); } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } System.out.println("Customer data added to the table with id id101"); }
请参阅上的完整示例
批量创建 (put) 和删除项目
您可以将一系列的 put 请求 (PutItemEnhancedRequest) 和删除请求 (DeleteItemEnhancedRequest) 批量发送到一个或多个表,然后在单个请求中发送所有更改。
SDK 提供了生成器模式来PutItemEnhancedRequest
为您创建。您只需要向该addPutItem()
方法提供一个 lambda 表达式,例如,如下例所示。builder -> builder.item(record2)
在第一次调用时,创建了一个DynamoDbTable对象并排队等候将三个项目添加到 Customer 表中WriteBatch.builder
。您可以根据需要在每批中多次调用addDeleteItem()
和addPutItem()
( WriteBatch.Builder 的一部分)。
要将对其他表的更改排入队列,请再次调用WriteBatch.builder()
并在中提供相应的DynamoDbTable对象mappedTableResource()
。如下所示,在使用音乐表并从表中删除一个项目的第二次WriteBatch.builder()
调用中。
导入
import com.example.dynamodb.Customer; import com.example.dynamodb.Music; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset;
代码
public static void putBatchRecords(DynamoDbEnhancedClient enhancedClient) { try { DynamoDbTable<Customer> customerMappedTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); DynamoDbTable<Music> musicMappedTable = enhancedClient.table("Music", TableSchema.fromBean(Music.class)); LocalDate localDate = LocalDate.parse("2020-04-07"); LocalDateTime localDateTime = localDate.atStartOfDay(); Instant instant = localDateTime.toInstant(ZoneOffset.UTC); Customer record2 = new Customer(); record2.setCustName("Fred Pink"); record2.setId("id110"); record2.setEmail("fredp@noserver.com"); record2.setRegistrationDate(instant) ; Customer record3 = new Customer(); record3.setCustName("Susan Pink"); record3.setId("id120"); record3.setEmail("spink@noserver.com"); record3.setRegistrationDate(instant) ; Customer record4 = new Customer(); record4.setCustName("Jerry orange"); record4.setId("id101"); record4.setEmail("jorange@noserver.com"); record4.setRegistrationDate(instant) ; BatchWriteItemEnhancedRequest batchWriteItemEnhancedRequest = BatchWriteItemEnhancedRequest.builder() .writeBatches( WriteBatch.builder(Customer.class) // add items to the Customer table .mappedTableResource(customerMappedTable) .addPutItem(builder -> builder.item(record2)) .addPutItem(builder -> builder.item(record3)) .addPutItem(builder -> builder.item(record4)) .build(), WriteBatch.builder(Music.class) // delete an item from the Music table .mappedTableResource(musicMappedTable) .addDeleteItem(builder -> builder.key( Key.builder().partitionValue("Famous Band").build())) .build()) .build(); // Add three items to the Customer table and delete one item from the Music table enhancedClient.batchWriteItem(batchWriteItemEnhancedRequest); System.out.println("done"); } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } }
请参阅上的完整示例
使用筛选的查询从表中获取项目
您可以根据可筛选的查询从表中获取项目,然后对查询结果执行操作。
对于下面的示例,假设该Customer
表包含以下各项:
id | 自定义名称 | 注册日期 | |
---|---|---|---|
id120 | spink@noserver.com | 苏珊·平克 | 2020-020 |
id101 | jorange@noserver.com | 杰里奥兰治 | 2020-020 |
id101 | tred@noserver.com | 汤姆·雷德 | 2020-020 |
ed110 | fredp@noserver.com | 弗雷德·平克 | 2020-020 |
以下步骤描述了以下queryTableFilter
方法中发生的情况。
-
生成一个表达式来筛选查询。
-
您可以通过首先将要匹配的值定义为AttributeValue对象来构建过滤器(在本示例中为 “Tom red”)。
-
您创建了一个
HashMap
以保存标记作为地图的键(在本示例中为 “: value”),并将AttributeValue
对象用作地图的值。 -
然后,您可以
Expression
使用过滤器表达式(“custName =: value”)和映射中的表达式值来构建。
-
-
生成一个
QueryConditional
对象。-
您构建一个
QueryConditional
对象以根据主键值 “id101” 选择项目。
-
-
生成查询请求并执行查询。
-
将 lambda 参数传递给 DynamoDbTable的
query()
方法中。SDK 使用参数的逻辑来构建最终的查询请求对象以发送到 DynamoDB 服务。
-
-
处理结果。
-
此示例通过计算返回的项目数并打印出
Customer
对象,在 for-each 循环中处理查询返回的可迭代结果。
-
以下日志输出显示了发送到 DynamoDB 服务的请求。
DEBUG org.apache.http.wire:87 - http-outgoing-0 >> "{"TableName":"Customer","FilterExpression":"custName = :value","KeyConditionExpression":"#AMZN_MAPPED_id = :AMZN_MAPPED_id","ExpressionAttributeNames":{"#AMZN_MAPPED_id":"id"},"ExpressionAttributeValues":{":AMZN_MAPPED_id":{"S":"id101"},":value":{"S":"Tom red"}}}"
注意
该QueryConditional接口有多种方法可用于构建查询,包括常见的条件语句,例如大于、小于和介于两者之间。
导入
import com.example.dynamodb.Customer; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import java.util.HashMap; import java.util.Map;
代码
public static Integer queryTableFilter(DynamoDbEnhancedClient enhancedClient) { Integer countOfCustomers = 0; try { DynamoDbTable<Customer> mappedTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); AttributeValue att = AttributeValue.builder() .s("Tom red") .build(); Map<String, AttributeValue> expressionValues = new HashMap<>(); expressionValues.put(":value", att); Expression expression = Expression.builder() .expression("custName = :value") .expressionValues(expressionValues) .build(); // Create a QueryConditional object to query by partitionValue. // Since the Customer table has a sort key attribute (email), we can use an expression // to filter the query results if multiple items have the same partition key value. QueryConditional queryConditional = QueryConditional .keyEqualTo(Key.builder().partitionValue("id101") .build()); // Perform the query for (Customer customer : mappedTable.query( r -> r.queryConditional(queryConditional) .filterExpression(expression) ).items()) { countOfCustomers++; System.out.println(customer); } } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } System.out.println("Done"); return countOfCustomers;
该代码返回一项。该QueryConditional
对象匹配 ID 为 “id101” 的项目,过滤器表达式进一步将返回的项目限制为等custName
于 “Tom red” 的项目。
请参阅上的完整示例
从表中检索(获取)所有项目
当您想要获取给定 DynamoDB 表中的所有记录时,请使用DynamoDbTable对象的scan()
items()
方法和方法来访问每个项目,您可以对其执行各种操作。例如,以下代码片段打印出Customer
表中每个项目的 ID 和客户名称。
导入
import com.example.dynamodb.Customer; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import java.util.Iterator;
代码
public static void scan( DynamoDbEnhancedClient enhancedClient) { try{ DynamoDbTable<Customer> custTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); Iterator<Customer> results = custTable.scan().items().iterator(); while (results.hasNext()) { Customer rec = results.next(); System.out.println("The record id is "+rec.getId()); System.out.println("The name is " +rec.getCustName()); } } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } System.out.println("Done"); }
请参阅上的完整示例
有关更多信息,请参阅《Amazon DynamoDB 开发人员指南》中的 DynamoDB 中处理项目。