DynamoDBMapper Class - Amazon DynamoDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

DynamoDBMapper Class

DynamoDBMapper 類別是 Amazon DynamoDB 的進入點。它提供 DynamoDB 端點的存取,也讓您可以存取多個資料表中的資料。它也讓您執行各種建立、讀取、更新和對項目進行刪除 (CRUD) 操作,以及執行查詢和掃描資料表。此類別提供下列使用 DynamoDB 的方法。

如需對應的 Javadoc 文件,請參閱《AWS SDK for Java API 參考》中的 DynamoDBMapper

save

將指定的物件儲存至資料表。您要儲存的物件是此方法的唯一必要參數。您可以使用 DynamoDBMapperConfig 物件來提供選用的組態參數。

如果具有相同主索引鍵的項目不存在,則此方法會在資料表中建立新的項目。如果具有相同主索引鍵的項目存在,則會更新現有項目。如果分割區索引鍵和排序索引鍵的類型是字串,並且標註 @DynamoDBAutoGeneratedKey,則會將隨機全域唯一識別符 (UUID) 授予它們 (若未初始化)。標註 @DynamoDBVersionAttribute 的版本欄位會遞增一。此外,如果更新版本欄位或產生索引鍵,則會因這項操作而更新傳入的物件。

根據預設,只會更新對應至已映射類別屬性的屬性。項目上的任何其他現有屬性則不受影響。不過,如果您指定 SaveBehavior.CLOBBER,則可以強制完全覆寫項目。

DynamoDBMapperConfig config = DynamoDBMapperConfig.builder() .withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.CLOBBER).build(); mapper.save(item, config);

如果您已啟用版本控制,則用戶端與伺服器端項目版本必須相符。不過,如果使用 SaveBehavior.CLOBBER 選項,則版本不需要相符。如需版本控制的詳細資訊,請參閱「含版本編號的樂觀鎖定」。

load

從資料表擷取項目。您必須提供要擷取之項目的主索引鍵。您可以使用 DynamoDBMapperConfig 物件來提供選用的組態參數。例如,您可以選擇性地請求強烈一致讀取,確保此方法只擷取最新的項目數值,如下列 Java 陳述式所示。

DynamoDBMapperConfig config = DynamoDBMapperConfig.builder() .withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT).build(); CatalogItem item = mapper.load(CatalogItem.class, item.getId(), config);

DynamoDB 預設會傳回數值最終一致的項目。如需 DynamoDB 最終一致性模型的資訊,請參閱 讀取一致性

刪除

刪除資料表中的項目。您必須傳入已映射類別的物件執行個體。

如果您已啟用版本控制,則用戶端與伺服器端項目版本必須相符。不過,如果使用 SaveBehavior.CLOBBER 選項,則版本不需要相符。如需版本控制的詳細資訊,請參閱「含版本編號的樂觀鎖定」。

query

查詢資料表或次要索引。

假設您有一個存放論壇主題回覆的 Reply 資料表。每個對話主旨都可以有零個以上的回覆。Reply 資料表的主索引鍵包含 IdReplyDateTime 欄位;其中,Id 是分割區索引鍵,而 ReplyDateTime 是主索引鍵的排序索引鍵。

Reply ( Id, ReplyDateTime, ... )

假設您已建立 Reply 類別與 DynamoDB 中對應 Reply 資料表之間的映射。下列 Java 程式碼使用 DynamoDBMapper 來尋找特定對話主旨在過去兩週的所有回覆。

範例
String forumName = "&DDB;"; String forumSubject = "&DDB; Thread 1"; String partitionKey = forumName + "#" + forumSubject; long twoWeeksAgoMilli = (new Date()).getTime() - (14L*24L*60L*60L*1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String twoWeeksAgoStr = df.format(twoWeeksAgo); Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS(partitionKey)); eav.put(":v2",new AttributeValue().withS(twoWeeksAgoStr.toString())); DynamoDBQueryExpression<Reply> queryExpression = new DynamoDBQueryExpression<Reply>() .withKeyConditionExpression("Id = :v1 and ReplyDateTime > :v2") .withExpressionAttributeValues(eav); List<Reply> latestReplies = mapper.query(Reply.class, queryExpression);

查詢會傳回 Reply 物件的集合。

query 方法預設會傳回「延遲載入」集合。它一開始只會傳回一頁的結果,然後視需要進行服務呼叫來取得下一頁。若要取得所有相符的項目,請逐一查看 latestReplies 集合。

請注意,在集合上呼叫 size() 方法將會載入所有結果,以提供準確的計數。這可能會導致耗用大量已佈建的輸送量,而在非常大型的資料表上可能甚至會耗盡 JVM 中的所有記憶體。

若要查詢索引,您必須先將索引建模為映射器類別。假設該Reply表具有名為 PostedBy-消息索引的全局次要索引。此索引的分割區索引鍵是 PostedBy,而排序索引鍵是 Message。索引中項目的類別定義將會如下。

@DynamoDBTable(tableName="Reply") public class PostedByMessage { private String postedBy; private String message; @DynamoDBIndexHashKey(globalSecondaryIndexName = "PostedBy-Message-Index", attributeName = "PostedBy") public String getPostedBy() { return postedBy; } public void setPostedBy(String postedBy) { this.postedBy = postedBy; } @DynamoDBIndexRangeKey(globalSecondaryIndexName = "PostedBy-Message-Index", attributeName = "Message") public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } // Additional properties go here. }

@DynamoDBTable 註釋指出此索引與 Reply 資料表建立關聯。此@DynamoDBIndexHashKey註釋代表索引的分割索引鍵 (PostedBy),並@DynamoDBIndexRangeKey代表索引的排序索引鍵 (訊息)。

您現在可以使用 DynamoDBMapper 來查詢索引,並擷取特定使用者所張貼的訊息子集。如果資料表和索引之間沒有衝突的映射,且映射器中已建立映射,則不需要指定索引名稱。映射器將根據主索引鍵和排序索引鍵推論。下列程式碼會查詢全域次要索引。因為全域次要索引支援最終一致讀取,但不支援強烈一致讀取,所以必須指定 withConsistentRead(false)

HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS("User A")); eav.put(":v2", new AttributeValue().withS("DynamoDB")); DynamoDBQueryExpression<PostedByMessage> queryExpression = new DynamoDBQueryExpression<PostedByMessage>() .withIndexName("PostedBy-Message-Index") .withConsistentRead(false) .withKeyConditionExpression("PostedBy = :v1 and begins_with(Message, :v2)") .withExpressionAttributeValues(eav); List<PostedByMessage> iList = mapper.query(PostedByMessage.class, queryExpression);

查詢會傳回 PostedByMessage 物件的集合。

queryPage

查詢資料表或次要索引,並傳回單頁的相符結果。與使用 query 方法相同,您必須指定分割區索引鍵值以及套用至排序索引鍵屬性的查詢篩選條件。不過,queryPage 只會傳回第一「頁」的資料;亦即,符合 1 MB 的資料量

scan

掃描整個資料表或次要索引。您可以選擇性地指定 FilterExpression 來篩選結果集。

假設您有一個存放論壇主題回覆的 Reply 資料表。每個對話主旨都可以有零個以上的回覆。Reply 資料表的主索引鍵包含 IdReplyDateTime 欄位;其中,Id 是分割區索引鍵,而 ReplyDateTime 是主索引鍵的排序索引鍵。

Reply ( Id, ReplyDateTime, ... )

如果您已將 Java 類別映射至 Reply 資料表,則可以使用 DynamoDBMapper 來掃描資料表。例如,下列 Java 程式碼會掃描整個 Reply 資料表,而且只會傳回特定一年的回覆。

範例
HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS("2015")); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("begins_with(ReplyDateTime,:v1)") .withExpressionAttributeValues(eav); List<Reply> replies = mapper.scan(Reply.class, scanExpression);

scan 方法預設會傳回「延遲載入」集合。它一開始只會傳回一頁的結果,然後視需要進行服務呼叫來取得下一頁。若要取得所有相符的項目,請逐一查看 replies 集合。

請注意,在集合上呼叫 size() 方法將會載入所有結果,以提供準確的計數。這可能會導致耗用大量已佈建的輸送量,而在非常大型的資料表上可能甚至會耗盡 JVM 中的所有記憶體。

若要掃描索引,您必須先將索引建模為映射器類別。假設 Reply 資料表有一個名為 PostedBy-Message-Index 的全域次要索引。此索引的分割區索引鍵是 PostedBy,而排序索引鍵是 Message。此索引的映射器類別顯示在 query 區段。它使用 @DynamoDBIndexHashKey@DynamoDBIndexRangeKey 註釋來指定索引的分割區索引鍵和排序索引鍵。

下列程式碼範例掃描 PostedBy-Message-Index。它不會使用掃描篩選條件,因此會將索引中的所有項目都傳回給您。

DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withIndexName("PostedBy-Message-Index") .withConsistentRead(false); List<PostedByMessage> iList = mapper.scan(PostedByMessage.class, scanExpression); Iterator<PostedByMessage> indexItems = iList.iterator();

scanPage

掃描資料表或次要索引,並傳回單頁的相符結果。與使用 scan 方法相同,您可以選擇性地指定 FilterExpression 來篩選結果集。不過,scanPage 只會傳回第一「頁」的資料;亦即,符合 1 MB 內的資料量。

parallelScan

執行整個資料表或次要索引的平行掃描。您可以指定資料表的一些邏輯區段,以及掃描表達式來篩選結果。parallelScan 會將掃描任務分到多個工作者 (一個邏輯區段一個工作者);工作者會平行處理資料,並傳回結果。

下列 Java 程式碼範例會對 Product 資料表執行平行掃描。

int numberOfThreads = 4; Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":n", new AttributeValue().withN("100")); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("Price <= :n") .withExpressionAttributeValues(eav); List<Product> scanResult = mapper.parallelScan(Product.class, scanExpression, numberOfThreads);

針對說明如何使用 parallelScan 的 Java 程式碼範例,請參閱「DynamoDBMapper 查詢和掃描操作」。

batchSave

使用 AmazonDynamoDB.batchWriteItem 方法的一或多個呼叫,將物件儲存至一或多個資料表。此方法不提供交易保證。

下列 Java 程式碼會將兩個項目 (書籍) 儲存至 ProductCatalog 資料表。

Book book1 = new Book(); book1.setId(901); book1.setProductCategory("Book"); book1.setTitle("Book 901 Title"); Book book2 = new Book(); book2.setId(902); book2.setProductCategory("Book"); book2.setTitle("Book 902 Title"); mapper.batchSave(Arrays.asList(book1, book2));

batchLoad

使用一或多個資料表的主索引鍵,以從中擷取多個項目。

下列 Java 程式碼會從兩個不同的資料表擷取兩個項目。

ArrayList<Object> itemsToGet = new ArrayList<Object>(); ForumItem forumItem = new ForumItem(); forumItem.setForumName("Amazon DynamoDB"); itemsToGet.add(forumItem); ThreadItem threadItem = new ThreadItem(); threadItem.setForumName("Amazon DynamoDB"); threadItem.setSubject("Amazon DynamoDB thread 1 message text"); itemsToGet.add(threadItem); Map<String, List<Object>> items = mapper.batchLoad(itemsToGet);

batchDelete

使用 AmazonDynamoDB.batchWriteItem 方法的一或多個呼叫,刪除一或多個資料表中的物件。此方法不提供交易保證。

下列 Java 程式碼會刪除 ProductCatalog 資料表中的兩個項目 (書籍)。

Book book1 = mapper.load(Book.class, 901); Book book2 = mapper.load(Book.class, 902); mapper.batchDelete(Arrays.asList(book1, book2));

batchWrite

使用 AmazonDynamoDB.batchWriteItem 方法的一或多個呼叫,將物件儲存至一或多個資料表,並刪除物件。此方法未提供交易保證或支援版本控制 (條件式放置或刪除)。

下列 Java 程式碼會將新項目寫入至 Forum 資料表、將新項目寫入至 Thread 資料表,並刪除 ProductCatalog 資料表中的項目。

// Create a Forum item to save Forum forumItem = new Forum(); forumItem.setName("Test BatchWrite Forum"); // Create a Thread item to save Thread threadItem = new Thread(); threadItem.setForumName("AmazonDynamoDB"); threadItem.setSubject("My sample question"); // Load a ProductCatalog item to delete Book book3 = mapper.load(Book.class, 903); List<Object> objectsToWrite = Arrays.asList(forumItem, threadItem); List<Book> objectsToDelete = Arrays.asList(book3); mapper.batchWrite(objectsToWrite, objectsToDelete);

transactionWrite

使用 AmazonDynamoDB.transactWriteItems 方法的一個呼叫,將物件儲存至一或多個資料表,並從中刪除物件。

如需交易特定例外狀況的清單,請參閱TransactWriteItems 錯誤。

如需 DynamoDB 交易與提供之不可部分完成性、一致性、隔離性和耐久性 (ACID) 保證的相關資訊,請參閱 Amazon DynamoDB Transactions

注意

此方法不支援下列項目:

以下 Java 程式碼會以交易的方式,將新項目寫入每個 ForumThread 資料表。

Thread s3ForumThread = new Thread(); s3ForumThread.setForumName("S3 Forum"); s3ForumThread.setSubject("Sample Subject 1"); s3ForumThread.setMessage("Sample Question 1"); Forum s3Forum = new Forum(); s3Forum.setName("S3 Forum"); s3Forum.setCategory("Amazon Web Services"); s3Forum.setThreads(1); TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest(); transactionWriteRequest.addPut(s3Forum); transactionWriteRequest.addPut(s3ForumThread); mapper.transactionWrite(transactionWriteRequest);

transactionLoad

使用 AmazonDynamoDB.transactGetItems 方法的一個呼叫,載入一或多個資料表中的物件。

如需交易特定例外狀況的清單,請參閱TransactGetItems 錯誤。

如需 DynamoDB 交易與提供之不可部分完成性、一致性、隔離性和耐久性 (ACID) 保證的相關資訊,請參閱 Amazon DynamoDB Transactions

以下 Java 程式碼會以交易的方式,將從每個 ForumThread 資料表載入一個項目。

Forum dynamodbForum = new Forum(); dynamodbForum.setName("DynamoDB Forum"); Thread dynamodbForumThread = new Thread(); dynamodbForumThread.setForumName("DynamoDB Forum"); TransactionLoadRequest transactionLoadRequest = new TransactionLoadRequest(); transactionLoadRequest.addLoad(dynamodbForum); transactionLoadRequest.addLoad(dynamodbForumThread); mapper.transactionLoad(transactionLoadRequest);

count

評估指定的掃描表達式,並傳回相符項目的計數。不傳回任何項目資料。

generateCreateTable請求

剖析代表 DynamoDB 資料表的 POJO 類別,並傳回該資料表的 CreateTableRequest

建立 Amazon S3 中物件的連結。您必須指定儲存貯體名稱和索引鍵名稱,以唯一識別儲存貯體中的物件。

若要使用 createS3Link,映射器類別必須定義 getter 和 setter 方法。下列程式碼範例透過將新的屬性和 getter/setter 方法新增至 CatalogItem 類別來說明這種情況。

@DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { ... public S3Link productImage; .... @DynamoDBAttribute(attributeName = "ProductImage") public S3Link getProductImage() { return productImage; } public void setProductImage(S3Link productImage) { this.productImage = productImage; } ... }

下列 Java 程式碼定義要寫入至 Product 資料表的新項目。此項目包含產品映像的連結;映像資料會上傳至 Amazon S3。

CatalogItem item = new CatalogItem(); item.setId(150); item.setTitle("Book 150 Title"); String myS3Bucket = "myS3bucket"; String myS3Key = "productImages/book_150_cover.jpg"; item.setProductImage(mapper.createS3Link(myS3Bucket, myS3Key)); item.getProductImage().uploadFrom(new File("/file/path/book_150_cover.jpg")); mapper.save(item);

S3Link 類別提供許多其他方法來操控 Amazon S3 中的物件。如需詳細資訊,請參閱 Javadocs for S3Link

獲得 3 ClientCache

傳回基礎 S3ClientCache 來存取 Amazon S3。S3ClientCacheAmazonS3Client 物件的智慧映射。如果您有多個客戶,S3ClientCache可以幫助您按 AWS 區域保持客戶組織,並可以根據需求創建新的 Amazon S3 客戶。