

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

# DynamoDBMapper Class
<a name="DynamoDBMapper.Methods"></a>



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

如需對應的 Javadoc 文件，請參閱《適用於 Java 的 AWS SDK API 參考》**中的 [DynamoDBMapper](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.html)。

**Topics**
+ [save](#DynamoDBMapper.Methods.save)
+ [load](#DynamoDBMapper.Methods.load)
+ [delete](#DynamoDBMapper.Methods.delete)
+ [query](#DynamoDBMapper.Methods.query)
+ [queryPage](#DynamoDBMapper.Methods.queryPage)
+ [掃描](#DynamoDBMapper.Methods.scan)
+ [scanPage](#DynamoDBMapper.Methods.scanPage)
+ [parallelScan](#DynamoDBMapper.Methods.parallelScan)
+ [batchSave](#DynamoDBMapper.Methods.batchSave)
+ [batchLoad](#DynamoDBMapper.Methods.batchLoad)
+ [batchDelete](#DynamoDBMapper.Methods.batchDelete)
+ [batchWrite](#DynamoDBMapper.Methods.batchWrite)
+ [transactionWrite](#DynamoDBMapper.Methods.transactionWrite)
+ [transactionLoad](#DynamoDBMapper.Methods.transactionLoad)
+ [count](#DynamoDBMapper.Methods.count)
+ [generateCreateTableRequest](#DynamoDBMapper.Methods.generateCreateTableRequest)
+ [createS3Link](#DynamoDBMapper.Methods.createS3Link)
+ [getS3ClientCache](#DynamoDBMapper.Methods.getS3ClientCache)

## save
<a name="DynamoDBMapper.Methods.save"></a>

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

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

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

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

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

## load
<a name="DynamoDBMapper.Methods.load"></a>

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

```
DynamoDBMapperConfig config = DynamoDBMapperConfig.builder()
    .withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT).build();

CatalogItem item = mapper.load(CatalogItem.class, item.getId(), config);
```

DynamoDB 預設會傳回數值最終一致的項目。如需 DynamoDB 最終一致性模式的資訊，請參閱 [DynamoDB 讀取一致性](HowItWorks.ReadConsistency.md)。

## delete
<a name="DynamoDBMapper.Methods.delete"></a>

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

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

## query
<a name="DynamoDBMapper.Methods.query"></a>

查詢資料表或次要索引。

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

```
Reply ( Id, ReplyDateTime, ... )
```

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

**Example**  

```
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-Message-Index* 的全域次要索引。此索引的分割區索引鍵是 `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` 表示索引的排序索引鍵 (*Message*)。

您現在可以使用 `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
<a name="DynamoDBMapper.Methods.queryPage"></a>

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

## 掃描
<a name="DynamoDBMapper.Methods.scan"></a>

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

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

```
Reply ( Id, ReplyDateTime, ... )
```

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

**Example**  

```
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](#DynamoDBMapper.Methods.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
<a name="DynamoDBMapper.Methods.scanPage"></a>

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

## parallelScan
<a name="DynamoDBMapper.Methods.parallelScan"></a>

執行整個資料表或次要索引的平行掃描。您可以指定資料表的一些邏輯區段，以及掃描表達式來篩選結果。`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);
```

## batchSave
<a name="DynamoDBMapper.Methods.batchSave"></a>

使用 `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
<a name="DynamoDBMapper.Methods.batchLoad"></a>

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

下列 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
<a name="DynamoDBMapper.Methods.batchDelete"></a>

使用 `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
<a name="DynamoDBMapper.Methods.batchWrite"></a>

使用 `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
<a name="DynamoDBMapper.Methods.transactionWrite"></a>

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

如需交易特定例外的清單，請參閱 [TransactWriteItems 錯誤](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html#API_TransactWriteItems_Errors)。

如需 DynamoDB 交易與提供之不可部分完成性、一致性、隔離性和耐久性 (ACID) 保證的相關資訊，請參閱 [Amazon DynamoDB Transactions](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transactions.html)。

**注意**  
 此方法不支援下列項目：  
[DynamoDBMapperConfig.SaveBehavior](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptionalConfig.html)。

以下 Java 程式碼會以交易的方式，將新項目寫入每個 `Forum` 和 `Thread` 資料表。

```
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
<a name="DynamoDBMapper.Methods.transactionLoad"></a>

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

如需交易特定例外的清單，請參閱 [TransactGetItems 錯誤](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html#API_TransactGetItems_Errors)。

如需 DynamoDB 交易與提供之不可部分完成性、一致性、隔離性和耐久性 (ACID) 保證的相關資訊，請參閱 [Amazon DynamoDB Transactions](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transactions.html)。

以下 Java 程式碼會以交易的方式，將從每個 `Forum` 和 `Thread` 資料表載入一個項目。

```
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
<a name="DynamoDBMapper.Methods.count"></a>

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

## generateCreateTableRequest
<a name="DynamoDBMapper.Methods.generateCreateTableRequest"></a>

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

## createS3Link
<a name="DynamoDBMapper.Methods.createS3Link"></a>

建立 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 amzn-s3-demo-bucket = "amzn-s3-demo-bucket";
String myS3Key = "productImages/book_150_cover.jpg";
item.setProductImage(mapper.createS3Link(amzn-s3-demo-bucket, myS3Key));

item.getProductImage().uploadFrom(new File("/file/path/book_150_cover.jpg"));

mapper.save(item);
```

`S3Link` 類別提供許多其他方法來操控 Amazon S3 中的物件。如需詳細資訊，請參閱 [Javadocs for `S3Link`](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/S3Link.html)。

## getS3ClientCache
<a name="DynamoDBMapper.Methods.getS3ClientCache"></a>

傳回基礎 `S3ClientCache` 來存取 Amazon S3。`S3ClientCache` 是 `AmazonS3Client` 物件的智慧映射。如果您有多個用戶端， `S3ClientCache`可協助您依 AWS 區域整理用戶端，並可隨需建立新的 Amazon S3 用戶端。