

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

# 適用於 DynamoDB 的更高階程式設計界面
<a name="HigherLevelInterfaces"></a>

 AWS SDKs 為應用程式提供使用 Amazon DynamoDB 的低階界面。這些用戶端類別和方法直接對應至低階 DynamoDB API。不過，當需要將複雜的資料類型映射至資料庫資料表中的項目時，許多開發人員會遭遇到網路斷線的感覺，或*阻抗不符*。使用低階資料庫界面，開發人員必須撰寫讀取或寫入物件資料至資料庫資料表的方法，反之亦然。物件類型和資料庫表格每個組合所需的額外程式碼數量似乎非常大。

為了簡化開發，適用於 Java 和 .NET AWS SDKs 提供額外的介面，具有更高層級的抽象。DynamoDB 的較高階界面可讓您定義程式中的物件與存放這些物件資料的資料庫表格之間的關係。定義此映射之後，您可以呼叫簡單的物件方法 (例如 `save`、`load` 或 `delete`)，也可以代表您自動叫用基礎低階 DynamoDB 操作。這允許您編寫以物件為中心的程式碼，而不是以資料庫為中心的程式碼。

DynamoDB 的高階程式設計界面可在適用於 Java 和 .NET AWS SDKs 中使用。

**Java**
+ [Java 1.x：DynamoDBMapper](DynamoDBMapper.md)
+ [Java 2.x：DynamoDB 增強型用戶端](DynamoDBEnhanced.md)

**.NET**
+ [在 DynamoDB 中使用 .NET 文件模型](DotNetSDKMidLevel.md)
+ [使用 .NET 物件持久性模型和 DynamoDB](DotNetSDKHighLevel.md)

# Java 1.x：DynamoDBMapper
<a name="DynamoDBMapper"></a>

**注意**  
適用於 Java 的 SDK 有兩個版本：1.x 和 2.x。1.x 版本已於 2024 年 1 月 12 日[宣布](https://aws.amazon.com/blogs/developer/announcing-end-of-support-for-aws-sdk-for-java-v1-x-on-december-31-2025/)終止支援。該版本將於 2025 年 12 月 31 日到期並終止支援。我們強烈建議您在新的開發作業使用 2.x 版本。

 適用於 Java 的 AWS SDK 提供 `DynamoDBMapper`類別，可讓您將用戶端類別映射至 Amazon DynamoDB 資料表。若要使用 `DynamoDBMapper`，請定義 DynamoDB 資料表中項目與程式碼中其對應物件執行個體之間的關係。`DynamoDBMapper` 類別也讓您執行各種建立、讀取、更新和對項目進行刪除 (CRUD) 操作，以及執行查詢和掃描資料表。

**Topics**
+ [DynamoDBMapper Class](DynamoDBMapper.Methods.md)
+ [適用於 Java 的 DynamoDBMapper 支援的資料類型](DynamoDBMapper.DataTypes.md)
+ [適用於 DynamoDB 的 Java 註釋](DynamoDBMapper.Annotations.md)
+ [DynamoDBMapper 的選用組態設定](DynamoDBMapper.OptionalConfig.md)
+ [含版本編號的 DynamoDB 及樂觀鎖定](DynamoDBMapper.OptimisticLocking.md)
+ [在 DynamoDB 中映射任意資料](DynamoDBMapper.ArbitraryDataMapping.md)
+ [DynamoDBMapper 範例](DynamoDBMapper.Examples.md)

**注意**  
`DynamoDBMapper` 類別不允許您建立、更新或刪除資料表。若要執行這些任務，請改為使用低階適用於 Java 的開發套件介面。

適用於 Java 的開發套件提供一組註釋類型，讓您可以將類別映射至資料表。例如，考量其 `Id` 為分割區索引鍵的 `ProductCatalog` 資料表。

```
ProductCatalog(Id, ...)
```

您可以將用戶端應用程式中的類別映射至 `ProductCatalog` 資料表，如下列 Java 程式碼所示。此程式碼定義名為 `CatalogItem` 的純舊 Java 物件 (POJO)，而此物件使用註釋將物件欄件映射至 DynamoDB 屬性名稱。

**Example**  

```
package com.amazonaws.codesamples;

import java.util.Set;

import software.amazon.dynamodb.datamodeling.DynamoDBAttribute;
import software.amazon.dynamodb.datamodeling.DynamoDBHashKey;
import software.amazon.dynamodb.datamodeling.DynamoDBIgnore;
import software.amazon.dynamodb.datamodeling.DynamoDBTable;

@DynamoDBTable(tableName="ProductCatalog")
public class CatalogItem {

    private Integer id;
    private String title;
    private String ISBN;
    private Set<String> bookAuthors;
    private String someProp;

    @DynamoDBHashKey(attributeName="Id")
    public Integer getId() { return id; }
    public void setId(Integer id) {this.id = id; }

    @DynamoDBAttribute(attributeName="Title")
    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }

    @DynamoDBAttribute(attributeName="ISBN")
    public String getISBN() { return ISBN; }
    public void setISBN(String ISBN) { this.ISBN = ISBN; }

    @DynamoDBAttribute(attributeName="Authors")
    public Set<String> getBookAuthors() { return bookAuthors; }
    public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; }

    @DynamoDBIgnore
    public String getSomeProp() { return someProp; }
    public void setSomeProp(String someProp) { this.someProp = someProp; }
}
```

在上述程式碼中，`@DynamoDBTable` 註釋會將 `CatalogItem` 類別映射至 `ProductCatalog` 資料表。您可以將個別類別執行個體存放為資料表中的項目。在類別定義中，`@DynamoDBHashKey` 註釋會將 `Id` 屬性映射至主索引鍵。

類別屬性預設會映射至資料表中的相同名稱屬性。`Title` 和 `ISBN` 屬性會映射至資料表中的相同名稱屬性。

DynamoDB 屬性的名稱符合類別中所宣告屬性的名稱時，`@DynamoDBAttribute` 註釋是選用項目。它們不同時，請搭配使用此註釋與 `attributeName` 參數，指定此屬性所對應的 DynamoDB 屬性。

在上述範例中，將 `@DynamoDBAttribute` 註釋新增至每個屬性，確保屬性名稱完全符合前個步驟中所建立的資料表，並與本指南的其他程式碼範例中所使用的屬性名稱一致。

類別定義可以有未映射至資料表中任何屬性的屬性。您可以新增 `@DynamoDBIgnore` 註釋來識別這些屬性。在上述範例中，`SomeProp` 屬性會標上 `@DynamoDBIgnore` 註釋。當您將 `CatalogItem` 執行個體上傳至資料表時，`DynamoDBMapper` 執行個體不會包含 `SomeProp` 屬性。此外，當您從資料表中擷取項目時，映射器不會傳回此屬性。

在您定義映射類別之後，可以使用 `DynamoDBMapper` 方法，將該類別的執行個體寫入至 `Catalog` 資料表中的對應項目。以下程式碼範例會示範此技術。

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

DynamoDBMapper mapper = new DynamoDBMapper(client);

CatalogItem item = new CatalogItem();
item.setId(102);
item.setTitle("Book 102 Title");
item.setISBN("222-2222222222");
item.setBookAuthors(new HashSet<String>(Arrays.asList("Author 1", "Author 2")));
item.setSomeProp("Test");

mapper.save(item);
```

下列程式碼範例示範如何擷取項目以及存取它的一些屬性：

```
CatalogItem partitionKey = new CatalogItem();

partitionKey.setId(102);
DynamoDBQueryExpression<CatalogItem> queryExpression = new DynamoDBQueryExpression<CatalogItem>()
    .withHashKeyValues(partitionKey);

List<CatalogItem> itemList = mapper.query(CatalogItem.class, queryExpression);

for (int i = 0; i < itemList.size(); i++) {
    System.out.println(itemList.get(i).getTitle());
    System.out.println(itemList.get(i).getBookAuthors());
}
```

`DynamoDBMapper` 提供直觀且自然的方式來處理 Java 內的 DynamoDB 資料。它也提供數項內建功能；例如，樂觀鎖定、ACID 交易、自動產生的分割區索引鍵和排序索引鍵值，以及物件版本控制。

# 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 用戶端。

# 適用於 Java 的 DynamoDBMapper 支援的資料類型
<a name="DynamoDBMapper.DataTypes"></a>

本節說明 Amazon DynamoDB 中支援的基本 Java 資料類型、集合和任意資料類型。

Amazon DynamoDB 支援下列基本 Java 資料類型和基本包裝函式類別。
+ `String`
+ `Boolean`, `boolean`
+ `Byte`, `byte`
+ `Date` (作為 [ISO\$18601](http://en.wikipedia.org/wiki/ISO_8601) 毫秒精確性字串，已轉移為 UTC)
+ `Calendar` (作為 [ISO\$18601](http://en.wikipedia.org/wiki/ISO_8601) 毫秒精確性字串，已轉移為 UTC)
+ `Long`, `long`
+ `Integer`, `int`
+ `Double`, `double`
+ `Float`, `float`
+ `BigDecimal`
+ `BigInteger`

**注意**  
如需有關 DynamoDB 命名規則和各種支援之資料類型的詳細資訊，請參閱 [Amazon DynamoDB 中支援的資料類型和命名規則](HowItWorks.NamingRulesDataTypes.md)。
空白的二進位值由 DynamoDBMapper 支援。
 AWS SDK for Java 2.x支援空白字串值。  
在適用於 Java 的 AWS SDK 1.x 中，DynamoDBMapper 支援讀取空的字串屬性值，但它不會寫入空的字串屬性值，因為這些屬性會從請求中刪除。

DynamoDB 支援 Java [Set](http://docs.oracle.com/javase/6/docs/api/java/util/Set.html)、[List](http://docs.oracle.com/javase/6/docs/api/java/util/List.html) 和 [Map](http://docs.oracle.com/javase/6/docs/api/java/util/Map.html) 集合類型。下表摘要說明如何將這些 Java 類型映射至 DynamoDB 類型。


****  

| Java 類型 | DynamoDB 類型 | 
| --- | --- | 
|  所有數字類型  |  `N` (數字類型)  | 
|  Strings  |  `S` (字串類型)   | 
|  Boolean  |  `BOOL` (布林類型)，0 或 1。  | 
|  ByteBuffer  |  `B` (二進位類型)  | 
|  Date  |  `S` (字串類型)。Date 值會以 ISO-8601 格式字串存放。  | 
| [Set](http://docs.oracle.com/javase/6/docs/api/java/util/Set.html) 集合類型 |  `SS` (字串集) 類型、`NS` (數字集) 類型或 `BS` (二進位集) 類型。  | 

 `DynamoDBTypeConverter` 介面可讓您將自己的任意資料類型映射至 DynamoDB 原生支援的資料類型。如需詳細資訊，請參閱[在 DynamoDB 中映射任意資料](DynamoDBMapper.ArbitraryDataMapping.md)。

# 適用於 DynamoDB 的 Java 註釋
<a name="DynamoDBMapper.Annotations"></a>

本節說明可用於將類別和屬性映射至 Amazon DynamoDB 中資料表和屬性的註釋。

如需對應的 Javadoc 文件，請參閱《[適用於 Java 的 AWS SDK API 參考](https://docs.aws.amazon.com/sdk-for-java/latest/reference/)》中的[註釋類型摘要](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/package-summary.html)。

**注意**  
在下列註釋中，只需要 `DynamoDBTable` 和 `DynamoDBHashKey`。

**Topics**
+ [DynamoDBAttribute](#DynamoDBMapper.Annotations.DynamoDBAttribute)
+ [DynamoDBAutoGeneratedKey](#DynamoDBMapper.Annotations.DynamoDBAutoGeneratedKey)
+ [DynamoDBAutoGeneratedTimestamp](#DynamoDBMapper.Annotations.DynamoDBAutoGeneratedTimestamp)
+ [DynamoDBDocument](#DynamoDBMapper.Annotations.DynamoDBDocument)
+ [DynamoDBHashKey](#DynamoDBMapper.Annotations.DynamoDBHashKey)
+ [DynamoDBIgnore](#DynamoDBMapper.Annotations.DynamoDBIgnore)
+ [DynamoDBIndexHashKey](#DynamoDBMapper.Annotations.DynamoDBIndexHashKey)
+ [DynamoDBIndexRangeKey](#DynamoDBMapper.Annotations.DynamoDBIndexRangeKey)
+ [DynamoDBRangeKey](#DynamoDBMapper.Annotations.DynamoDBRangeKey)
+ [DynamoDBTable](#DynamoDBMapper.Annotations.DynamoDBTable)
+ [DynamoDBTypeConverted](#DynamoDBMapper.Annotations.DynamoDBTypeConverted)
+ [DynamoDBTyped](#DynamoDBMapper.Annotations.DynamoDBTyped)
+ [DynamoDBVersionAttribute](#DynamoDBMapper.Annotations.DynamoDBVersionAttribute)

## DynamoDBAttribute
<a name="DynamoDBMapper.Annotations.DynamoDBAttribute"></a>

將屬性映射至資料表屬性。每個類別屬性預設會映射至同名的項目屬性。不過，如果名稱不同，您可以使用此註釋將屬性 (property) 映射至屬性 (attribute)。在下列 Java 程式碼片段中，`DynamoDBAttribute` 會將 `BookAuthors` 屬性映射至資料表中的 `Authors` 屬性名稱。

```
@DynamoDBAttribute(attributeName = "Authors")
public List<String> getBookAuthors() { return BookAuthors; }
public void setBookAuthors(List<String> BookAuthors) { this.BookAuthors = BookAuthors; }
```

將物件儲存至資料表時，`DynamoDBMapper` 使用 `Authors` 做為屬性名稱。

## DynamoDBAutoGeneratedKey
<a name="DynamoDBMapper.Annotations.DynamoDBAutoGeneratedKey"></a>

將分割區索引鍵或排序索引鍵屬性標示為自動產生。儲存這些屬性時，`DynamoDBMapper`​ 會產生隨機 [​UUID](http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html)。只有字串屬性才能標示為自動產生的索引鍵。

以下是示範使用自動產生索引鍵參數的範例。

```
@DynamoDBTable(tableName="AutoGeneratedKeysExample")
public class AutoGeneratedKeys {
    private String id;
    private String payload;

    @DynamoDBHashKey(attributeName = "Id")
    @DynamoDBAutoGeneratedKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    @DynamoDBAttribute(attributeName="payload")
    public String getPayload() { return this.payload; }
    public void setPayload(String payload) { this.payload = payload; }

    public static void saveItem() {
        AutoGeneratedKeys obj = new AutoGeneratedKeys();
        obj.setPayload("abc123");

        // id field is null at this point
        DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient);
        mapper.save(obj);

        System.out.println("Object was saved with id " + obj.getId());
    }
}
```

## DynamoDBAutoGeneratedTimestamp
<a name="DynamoDBMapper.Annotations.DynamoDBAutoGeneratedTimestamp"></a>

自動產生時間戳記。

```
@DynamoDBAutoGeneratedTimestamp(strategy=DynamoDBAutoGenerateStrategy.ALWAYS)
public Date getLastUpdatedDate() { return lastUpdatedDate; }
public void setLastUpdatedDate(Date lastUpdatedDate) { this.lastUpdatedDate = lastUpdatedDate; }
```

或者，可以透過提供策略屬性來定義自動產生策略。預設值為 `ALWAYS`。

## DynamoDBDocument
<a name="DynamoDBMapper.Annotations.DynamoDBDocument"></a>

指出類別可以序列化為 Amazon DynamoDB 文件。

例如，假設您要將 JSON 文件映射至 Map (`M`) 類型的 DynamoDB 屬性。下列程式碼範例定義包含 Map 類型之巢狀屬性 (Pictures) 的項目。

```
public class ProductCatalogItem {

    private Integer id;  //partition key
    private Pictures pictures;
    /* ...other attributes omitted... */

    @DynamoDBHashKey(attributeName="Id")
    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    @DynamoDBAttribute(attributeName="Pictures")
    public Pictures getPictures() { return pictures;}
    public void setPictures(Pictures pictures) {this.pictures = pictures;}

    // Additional properties go here.

    @DynamoDBDocument
    public static class Pictures {
        private String frontView;
        private String rearView;
        private String sideView;

        @DynamoDBAttribute(attributeName = "FrontView")
        public String getFrontView() { return frontView; }
        public void setFrontView(String frontView) { this.frontView = frontView; }

        @DynamoDBAttribute(attributeName = "RearView")
        public String getRearView() { return rearView; }
        public void setRearView(String rearView) { this.rearView = rearView; }

        @DynamoDBAttribute(attributeName = "SideView")
        public String getSideView() { return sideView; }
        public void setSideView(String sideView) { this.sideView = sideView; }

     }
}
```

然後您就可儲存新的 `ProductCatalog` 項目，並具有 `Pictures`，如下列範例所示。

```
ProductCatalogItem item = new ProductCatalogItem();

Pictures pix = new Pictures();
pix.setFrontView("http://example.com/products/123_front.jpg");
pix.setRearView("http://example.com/products/123_rear.jpg");
pix.setSideView("http://example.com/products/123_left_side.jpg");
item.setPictures(pix);

item.setId(123);

mapper.save(item);
```

產生的 `ProductCatalog`項目看起來將會如下 (JSON 格式)。

```
{
  "Id" : 123
  "Pictures" : {
    "SideView" : "http://example.com/products/123_left_side.jpg",
    "RearView" : "http://example.com/products/123_rear.jpg",
    "FrontView" : "http://example.com/products/123_front.jpg"
  }
}
```

## DynamoDBHashKey
<a name="DynamoDBMapper.Annotations.DynamoDBHashKey"></a>

將類別屬性映射至資料表的分割區索引鍵。此屬性必須是純量字串、數字或二進位類型的其中之一。此屬性不能是集合類型。

假設您的 `ProductCatalog` 資料表將 `Id` 作為主索引鍵。下列 Java 程式碼定義 `CatalogItem` 類別，並使用 `@DynamoDBHashKey` 標籤將其 `Id` 屬性映射至 `ProductCatalog` 資料表的主索引鍵。

```
@DynamoDBTable(tableName="ProductCatalog")
public class CatalogItem {
    private Integer Id;
   @DynamoDBHashKey(attributeName="Id")
   public Integer getId() {
        return Id;
   }
   public void setId(Integer Id) {
        this.Id = Id;
   }
   // Additional properties go here.
}
```

## DynamoDBIgnore
<a name="DynamoDBMapper.Annotations.DynamoDBIgnore"></a>

指出應該忽略相關聯屬性的 `DynamoDBMapper` 執行個體。將資料儲存至資料表時，`DynamoDBMapper` 不會將此屬性儲存至資料表。

 套用至 getter 方法或非模組化屬性的類別欄位。若該註釋是直接套用至類別欄位，則必須在相同的類別宣告相對應的 getter 和 setter。

## DynamoDBIndexHashKey
<a name="DynamoDBMapper.Annotations.DynamoDBIndexHashKey"></a>

將類別屬性映射至全域次要索引的分割區索引鍵。此屬性必須是純量字串、數字或二進位類型的其中之一。此屬性不能是集合類型。

如果您需要對全域次要索引進行 `Query`，請使用此註釋。您必須指定索引名稱 (`globalSecondaryIndexName`)。如果類別屬性的名稱與索引的分割區索引鍵不同，您也必須指定該索引屬性的名稱 (`attributeName`)。

## DynamoDBIndexRangeKey
<a name="DynamoDBMapper.Annotations.DynamoDBIndexRangeKey"></a>

將類別屬性映射至全域次要索引或本機次要索引的排序索引鍵。此屬性必須是純量字串、數字或二進位類型的其中之一。此屬性不能是集合類型。

如果您需要對本機次要索引或全域次要索引進行 `Query`，並且想要使用索引的排序索引鍵來縮小您結果的範圍，請使用此註釋。您必須指定索引名稱 (`globalSecondaryIndexName` 或 `localSecondaryIndexName`)。如果類別屬性的名稱與索引的排序索引鍵不同，您也必須指定該索引屬性的名稱 (`attributeName`)。

## DynamoDBRangeKey
<a name="DynamoDBMapper.Annotations.DynamoDBRangeKey"></a>

將類別屬性映射至資料表的排序索引鍵。此屬性必須是純量字串、數字或二進位類型的其中之一。它不能是集合類型。

如果主索引鍵是複合 (分割區索引鍵和排序索引鍵)，您可以使用此標籤，將類別欄位映射至排序索引鍵。例如，假設您的 `Reply` 資料表存放論壇主題回覆。每個對話都可以有許多回覆。因此，此資料表的主索引鍵是 `ThreadId` 和 `ReplyDateTime`。分割區索引鍵是 `ThreadId`，而排序索引鍵是 `ReplyDateTime`。

下列 Java 程式碼定義 `Reply` 類別，並將它映射至 `Reply` 資料表。它會使用 `@DynamoDBHashKey` 和 `@DynamoDBRangeKey` 標籤來識別映射至主索引鍵的類別屬性。

```
@DynamoDBTable(tableName="Reply")
public class Reply {
    private Integer id;
    private String replyDateTime;

    @DynamoDBHashKey(attributeName="Id")
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }

    @DynamoDBRangeKey(attributeName="ReplyDateTime")
    public String getReplyDateTime() { return replyDateTime; }
    public void setReplyDateTime(String replyDateTime) { this.replyDateTime = replyDateTime; }

   // Additional properties go here.
}
```

## DynamoDBTable
<a name="DynamoDBMapper.Annotations.DynamoDBTable"></a>

識別 DynamoDB 中的目標資料表。下列 Java 程式碼定義 `Developer` 類別，並將它映射至 DynamoDB 中的 `People` 資料表。

```
@DynamoDBTable(tableName="People")
public class Developer { ...}
```

`@DynamoDBTable` 註釋可以予以繼承。任何繼承自 `Developer` 類別的新類別也會映射至 `People` 資料表。例如，假設您建立繼承自 `Lead` 類別的 `Developer` 類別。因為您已將 `Developer` 類別映射至 `People` 資料表，所以也會將 `Lead` 類別物件存放至相同的資料表。

`@DynamoDBTable` 也可以予以覆寫。任何繼承自 `Developer` 類別的新類別預設會映射至相同的 `People` 資料表。不過，您可以覆寫此預設映射。例如，如果您建立繼承自 `Developer` 類別的類別，則可以新增 `@DynamoDBTable` 註釋，明確地將它映射至另一個資料表，如下列 Java 程式碼範例所示。

```
@DynamoDBTable(tableName="Managers")
public class Manager extends Developer { ...}
```

## DynamoDBTypeConverted
<a name="DynamoDBMapper.Annotations.DynamoDBTypeConverted"></a>

將屬性標示為使用自訂類型轉換器的註釋。可以標註於使用者定義的註釋，以將其他屬性傳遞給 `DynamoDBTypeConverter`。

 `DynamoDBTypeConverter` 介面可讓您將自己的任意資料類型映射至 DynamoDB 原生支援的資料類型。如需詳細資訊，請參閱[在 DynamoDB 中映射任意資料](DynamoDBMapper.ArbitraryDataMapping.md)。

## DynamoDBTyped
<a name="DynamoDBMapper.Annotations.DynamoDBTyped"></a>

覆寫標準屬性類型繫結的註釋。如果套用標準類型的預設屬性繫結，則該類型不需要註釋。

## DynamoDBVersionAttribute
<a name="DynamoDBMapper.Annotations.DynamoDBVersionAttribute"></a>

識別用於存放樂觀鎖定版本編號的類別屬性。`DynamoDBMapper`​ 在儲存新的項目時會將版本編號指派給此屬性，並在每次您更新項目時予以遞增。僅支援數字純量類型。如需資料類型的詳細資訊，請參閱 [資料類型](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes)。如需版本控制的詳細資訊，請參閱「[含版本編號的 DynamoDB 及樂觀鎖定](DynamoDBMapper.OptimisticLocking.md)」。

# DynamoDBMapper 的選用組態設定
<a name="DynamoDBMapper.OptionalConfig"></a>

當您建立 `DynamoDBMapper` 執行個體時，會有特定預設行為；您可以使用 `DynamoDBMapperConfig` 類別來覆寫這些預設值。

下列程式碼片段會使用自訂設定來建立 `DynamoDBMapper`：

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder()
        .withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.CLOBBER)
        .withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT)
        .withTableNameOverride(null)
        .withPaginationLoadingStrategy(DynamoDBMapperConfig.PaginationLoadingStrategy.EAGER_LOADING)
    .build();

DynamoDBMapper mapper = new DynamoDBMapper(client, mapperConfig);
```

如需詳細資訊，請參閱《[適用於 Java 的 AWS SDK API 參考](https://docs.aws.amazon.com/sdk-for-java/latest/reference/)》中的 [https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.html](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.html)。

您可以針對 `DynamoDBMapperConfig` 執行個體使用下列引數：
+ `DynamoDBMapperConfig.ConsistentReads` 列舉值：
  + `EVENTUAL`：映射器執行個體使用最終一致讀取請求。
  + `CONSISTENT`：映射器執行個體使用高度一致性讀取請求。您可以搭配使用這個選用設定與 `load`、`query` 或 `scan` 操作。高度一致性讀取具有效能和帳單隱憂；如需詳細資訊，請參閱 DynamoDB [產品詳細資訊頁面](https://aws.amazon.com/dynamodb)。

  如果您未指定映射器執行個體的讀取一致性設定，則預設值為 `EVENTUAL`。
**注意**  
此值僅適用於 DynamoDBMapper 的 `query`、`querypage`、`load` 和 `batch load` 操作。
+ `DynamoDBMapperConfig.PaginationLoadingStrategy` 列舉值：控制映射器執行個體如何處理分頁資料清單，例如 `query` 或 `scan` 的結果：
  + `LAZY_LOADING`：映射器執行個體會在可能時載入資料，並將所有載入的結果保留在記憶體中。
  + `EAGER_LOADING`：映射器執行個體會在初始化清單時立即載入資料。
  + `ITERATION_ONLY`：您只能使用從清單中讀取的迭代器。在迭代期間，清單會先清除所有先前的結果，再載入下一頁，因此清單最多會將一頁的已載入結果保留在記憶體中。這也表示清單只能重複使用一次。處理大型項目時，建議使用此策略，以減少記憶體負擔。

  如果您未指定映射器執行個體的分頁載入策略，則預設值為 `LAZY_LOADING`。
+ `DynamoDBMapperConfig.SaveBehavior` 列舉值：指定映射器執行個體在儲存操作期間應該如何處理屬性：
  + `UPDATE`：在儲存操作期間，會更新所有建模屬性，未建模屬性則不受影響。基本數字類型 (byte、int、long) 設定為 0。物件類型設定為 Null。
  + `CLOBBER`：在儲存操作期間，清除和取代所有屬性 (包含未建模屬性)。透過刪除並重新建立項目來完成這項操作。使用版本控制的欄位限制條件也會予以忽略。

   如果您未指定映射器執行個體的儲存行為，則預設值為 `UPDATE`。
**注意**  
DynamoDBMapper 交易操作不支援 `DynamoDBMapperConfig.SaveBehavior` 列舉。
+ `DynamoDBMapperConfig.TableNameOverride` 物件：指示映射器執行個體忽略類別之 `DynamoDBTable` 註釋所指定的資料表名稱，並改為使用您提供的不同資料表名稱。在執行時期將資料分割為多個資料表時，這十分有用。

您可以視需要覆寫每個操作的 `DynamoDBMapper` 預設組態物件。

# 含版本編號的 DynamoDB 及樂觀鎖定
<a name="DynamoDBMapper.OptimisticLocking"></a>

*樂觀鎖定*是一種策略，確保您要更新 (或刪除) 的用戶端項目與 Amazon DynamoDB 中的項目相同。如果您使用此策略，則會保護其他項目的寫入不會覆寫資料庫寫入，反之亦然。

使用樂觀鎖定，每個項目都有做為版本編號的屬性。如果您從資料表中擷取項目，則應用程式會記錄該項目的版本編號。您可以更新項目，但只有在伺服器端的版本編號尚未變更時。若版本不相符，表示已有其他人在您之前進行修改。更新嘗試失敗，因為您有此項目的過期版本。如果發生這種情況，請檢索項目然後嘗試進行更新以重試一次。樂觀鎖定預防您意外覆寫其他人所作的變更。同時也預防其他人意外覆寫您所作的變更。

雖然您可以實作自己的樂觀鎖定策略，但 適用於 Java 的 AWS SDK 提供 `@DynamoDBVersionAttribute`註釋。在資料表的映射類別中，您指定一個屬性來存放版本編號，並使用此註釋進行標示。當您儲存物件時，DynamoDB 資料表中的對應項目會有屬性可存放版本編號。當您第一次儲存物件時，`DynamoDBMapper` 會指派版本編號，並在每次更新項目時自動遞增版本編號。只有在用戶端物件版本與 DynamoDB 資料表中項目的對應版本編號相符時，您的更新或刪除請求才會成功。

 如果發生下列情況，則會擲回 `ConditionalCheckFailedException`：
+  您使用含 `@DynamoDBVersionAttribute` 的樂觀鎖定，而且伺服器上的版本值與用戶端上的值不同。
+  您可以搭配使用 `DynamoDBMapper` 與 `DynamoDBSaveExpression`，以在儲存資料時指定自己的條件式限制條件，而且這些限制條件會失敗。

**注意**  
DynamoDB 全域資料表會在並行更新間使用「最後寫入者獲勝」核對機制。如果您使用的是全域資料表，最後寫入者政策獲勝。因此，在此情況下，鎖定政策不會如預期般運作。
`DynamoDBMapper` 交易寫入操作不支援同一物件的 `@DynamoDBVersionAttribute` 標註和條件表達式。如果交易寫入內的物件以 `@DynamoDBVersionAttribute` 標註，且具有條件表達式，則會拋出 SdkClientException。

例如，下列 Java 程式碼定義有數個屬性的 `CatalogItem` 類別。`Version` 屬性會標上 `@DynamoDBVersionAttribute` 註釋。

**Example**  

```
@DynamoDBTable(tableName="ProductCatalog")
public class CatalogItem {

    private Integer id;
    private String title;
    private String ISBN;
    private Set<String> bookAuthors;
    private String someProp;
    private Long version;

    @DynamoDBHashKey(attributeName="Id")
    public Integer getId() { return id; }
    public void setId(Integer Id) { this.id = Id; }

    @DynamoDBAttribute(attributeName="Title")
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }

    @DynamoDBAttribute(attributeName="ISBN")
    public String getISBN() { return ISBN; }
    public void setISBN(String ISBN) { this.ISBN = ISBN;}

    @DynamoDBAttribute(attributeName = "Authors")
    public Set<String> getBookAuthors() { return bookAuthors; }
    public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; }

    @DynamoDBIgnore
    public String getSomeProp() { return someProp;}
    public void setSomeProp(String someProp) {this.someProp = someProp;}

    @DynamoDBVersionAttribute
    public Long getVersion() { return version; }
    public void setVersion(Long version) { this.version = version;}
}
```

您可以將 `@DynamoDBVersionAttribute` 註釋套用至基本包裝函式類別所提供的可為 Null 類型，而基本包裝函式類別提供可為 Null 類型 (例如 `Long` 和 `Integer`)。

樂觀鎖定對這些 `DynamoDBMapper` 方法的影響如下：
+ `save`：針對新項目，`DynamoDBMapper` 會指派初始版本編號 1。如果您擷取項目，請更新其一或多個屬性並嘗試儲存變更，只有在用戶端的版本編號與伺服器端的相符時，儲存操作才會成功。`DynamoDBMapper` 會自動遞增版本編號。
+ `delete`：`delete` 方法會採用物件作為參數，而 `DynamoDBMapper` 會在刪除項目之前執行版本檢查。如果請求中指定 `DynamoDBMapperConfig.SaveBehavior.CLOBBER`，則可以停用版本檢查。

  `DynamoDBMapper` 內的樂觀鎖定內部實作，使用 DynamoDB 所提供的條件式更新和條件式刪除支援。
+ `transactionWrite` —
  + `Put`：針對新項目，`DynamoDBMapper` 會指派初始版本編號 1。如果您擷取項目，請更新其一或多個屬性並嘗試儲存變更，只有在用戶端的版本編號與伺服器端的相符時，Put 操作才會成功。`DynamoDBMapper` 會自動遞增版本編號。
  + `Update`：針對新項目，`DynamoDBMapper` 會指派初始版本編號 1。如果您擷取項目，請更新其一或多個屬性並嘗試儲存變更，只有在用戶端的版本編號與伺服器端的相符時，update 操作才會成功。`DynamoDBMapper` 會自動遞增版本編號。
  + `Delete`：`DynamoDBMapper` 會在刪除項目之前執行版本檢查。只有用戶端與伺服器端的版本號碼相符時，delete 操作才會成功。
  + `ConditionCheck`：不支援 `ConditionCheck` 操作的 `@DynamoDBVersionAttribute` 註釋。以 `@DynamoDBVersionAttribute` 標註 `ConditionCheck` 項目時，會拋出 SdkClientException。

## 停用樂觀鎖定
<a name="DynamoDBMapper.OptimisticLocking.Disabling"></a>

若要停用樂觀鎖定，您可以將 `DynamoDBMapperConfig.SaveBehavior` 列舉值從 `UPDATE` 變更為 `CLOBBER`。您可以建立跳過版本檢查的 `DynamoDBMapperConfig` 執行個體來執行這項操作，並將此執行個體用於所有請求。如需 `DynamoDBMapperConfig.SaveBehavior` 和其他選用 `DynamoDBMapper` 參數的資訊，請參閱「[DynamoDBMapper 的選用組態設定](DynamoDBMapper.OptionalConfig.md)」。

您也只能設定特定操作的鎖定行為。例如，下列 Java 程式碼片段使用 `DynamoDBMapper` 來儲存型錄項目。指定 `DynamoDBMapperConfig.SaveBehavior` 的方式是將選用 `DynamoDBMapperConfig` 參數新增至 `save` 方法。

**注意**  
transactionWrite 方法不支援 DynamoDBMapperConfig.SaveBehavior 組態。不支援停用 transactionWrite 的樂觀鎖定。

**Example**  

```
DynamoDBMapper mapper = new DynamoDBMapper(client);

// Load a catalog item.
CatalogItem item = mapper.load(CatalogItem.class, 101);
item.setTitle("This is a new title for the item");
...
// Save the item.
mapper.save(item,
    new DynamoDBMapperConfig(
        DynamoDBMapperConfig.SaveBehavior.CLOBBER));
```

# 在 DynamoDB 中映射任意資料
<a name="DynamoDBMapper.ArbitraryDataMapping"></a>

除了支援的 Java 類型之外 (請參閱 [適用於 Java 的 DynamoDBMapper 支援的資料類型](DynamoDBMapper.DataTypes.md))，您還可以使用應用程式中未直接映射至 Amazon DynamoDB 類型的類型。若要映射這些類型，您必須提供將複雜類型轉換為 DynamoDB 支援之類型的實作 (反之亦然)，並使用 `@DynamoDBTypeConverted` 註釋來標註複雜類型存取子方法。轉換器程式碼會在儲存或載入物件時轉換資料。它也用於使用複雜類型的所有操作。請注意，在查詢和掃描操作期間比較資料時，會針對 DynamoDB 中所存放的資料進行比較。

例如，請考慮下列可定義本身為 `CatalogItem` 之 `Dimension` 屬性的 `DimensionType` 類別。此屬性會將項目維度存放為高度、寬度和厚度。假設您決定將這些項目維度存放為 DynamoDB 中的字串 (例如 8.5x11x.05)。下列範例提供轉換器程式碼，以將 `DimensionType` 物件轉換為字串以及將字串轉換為 `DimensionType`。



**注意**  
此程式碼範例假設您已根據 [在 DynamoDB 中建立資料表，以及載入程式碼範例的資料](SampleData.md) 一節的說明將資料載入 DynamoDB 的帳戶。  
如需執行下列範例的逐步說明，請參閱「[Java 程式碼範例](CodeSamples.Java.md)」。

**Example**  

```
public class DynamoDBMapperExample {

    static AmazonDynamoDB client;

    public static void main(String[] args) throws IOException {

        // Set the AWS region you want to access.
        Regions usWest2 = Regions.US_WEST_2;
        client = AmazonDynamoDBClientBuilder.standard().withRegion(usWest2).build();

        DimensionType dimType = new DimensionType();
        dimType.setHeight("8.00");
        dimType.setLength("11.0");
        dimType.setThickness("1.0");

        Book book = new Book();
        book.setId(502);
        book.setTitle("Book 502");
        book.setISBN("555-5555555555");
        book.setBookAuthors(new HashSet<String>(Arrays.asList("Author1", "Author2")));
        book.setDimensions(dimType);

        DynamoDBMapper mapper = new DynamoDBMapper(client);
        mapper.save(book);

        Book bookRetrieved = mapper.load(Book.class, 502);
        System.out.println("Book info: " + "\n" + bookRetrieved);

        bookRetrieved.getDimensions().setHeight("9.0");
        bookRetrieved.getDimensions().setLength("12.0");
        bookRetrieved.getDimensions().setThickness("2.0");

        mapper.save(bookRetrieved);

        bookRetrieved = mapper.load(Book.class, 502);
        System.out.println("Updated book info: " + "\n" + bookRetrieved);
    }

    @DynamoDBTable(tableName = "ProductCatalog")
    public static class Book {
        private int id;
        private String title;
        private String ISBN;
        private Set<String> bookAuthors;
        private DimensionType dimensionType;

        // Partition key
        @DynamoDBHashKey(attributeName = "Id")
        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        @DynamoDBAttribute(attributeName = "Title")
        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        @DynamoDBAttribute(attributeName = "ISBN")
        public String getISBN() {
            return ISBN;
        }

        public void setISBN(String ISBN) {
            this.ISBN = ISBN;
        }

        @DynamoDBAttribute(attributeName = "Authors")
        public Set<String> getBookAuthors() {
            return bookAuthors;
        }

        public void setBookAuthors(Set<String> bookAuthors) {
            this.bookAuthors = bookAuthors;
        }

        @DynamoDBTypeConverted(converter = DimensionTypeConverter.class)
        @DynamoDBAttribute(attributeName = "Dimensions")
        public DimensionType getDimensions() {
            return dimensionType;
        }

        @DynamoDBAttribute(attributeName = "Dimensions")
        public void setDimensions(DimensionType dimensionType) {
            this.dimensionType = dimensionType;
        }

        @Override
        public String toString() {
            return "Book [ISBN=" + ISBN + ", bookAuthors=" + bookAuthors + ", dimensionType= "
                    + dimensionType.getHeight() + " X " + dimensionType.getLength() + " X "
                    + dimensionType.getThickness()
                    + ", Id=" + id + ", Title=" + title + "]";
        }
    }

    static public class DimensionType {

        private String length;
        private String height;
        private String thickness;

        public String getLength() {
            return length;
        }

        public void setLength(String length) {
            this.length = length;
        }

        public String getHeight() {
            return height;
        }

        public void setHeight(String height) {
            this.height = height;
        }

        public String getThickness() {
            return thickness;
        }

        public void setThickness(String thickness) {
            this.thickness = thickness;
        }
    }

    // Converts the complex type DimensionType to a string and vice-versa.
    static public class DimensionTypeConverter implements DynamoDBTypeConverter<String, DimensionType> {

        @Override
        public String convert(DimensionType object) {
            DimensionType itemDimensions = (DimensionType) object;
            String dimension = null;
            try {
                if (itemDimensions != null) {
                    dimension = String.format("%s x %s x %s", itemDimensions.getLength(), itemDimensions.getHeight(),
                            itemDimensions.getThickness());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return dimension;
        }

        @Override
        public DimensionType unconvert(String s) {

            DimensionType itemDimension = new DimensionType();
            try {
                if (s != null && s.length() != 0) {
                    String[] data = s.split("x");
                    itemDimension.setLength(data[0].trim());
                    itemDimension.setHeight(data[1].trim());
                    itemDimension.setThickness(data[2].trim());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            return itemDimension;
        }
    }
}
```

# DynamoDBMapper 範例
<a name="DynamoDBMapper.Examples"></a>

適用於 Java 的 AWS SDK 提供 `DynamoDBMapper` 類別，可讓您將用戶端類別映射至 DynamoDB 資料表。若要使用 `DynamoDBMapper`，請定義 DynamoDB 資料表中項目與程式碼中其對應物件執行個體之間的關係。`DynamoDBMapper` 類別也讓您執行各種建立、讀取、更新和對項目進行刪除 (CRUD) 操作，以及執行查詢和掃描資料表。

若要進一步了解如何使用 `DynamoDBMapper`，請參閱《*適用於 Java 1.x 的 AWS SDK 開發人員指南*》中[使用適用於 Java 的 AWS SDK 的 DynamoDB 範例](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-dynamodb.html)。

# Java 2.x：DynamoDB 增強型用戶端
<a name="DynamoDBEnhanced"></a>

DynamoDB 增強型用戶端是適用於 Java 的 AWS SDK 2 (v2) 版中的高階程式庫。提供將客戶端類別映射到 DynamoDB 資料表的直接方式。您要在自己的程式碼中定義資料表及其對應模型類別之間的關係。定義關係之後，您可以直觀地對 DynamoDB 中的資料表或項目執行各種建立、讀取、更新或刪除 (CRUD) 操作。

如需有關如何將增強型用戶端與 DynamoDB 搭配使用的詳細資訊，請參閱[適用於 Java 的 AWS SDK 2.x 中的使用 DynamoDB 增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)。

# 在 DynamoDB 中使用 .NET 文件模型
<a name="DotNetSDKMidLevel"></a>

適用於 .NET 的 AWS SDK 提供文件模型類別，包裝一部分低階 Amazon DynamoDB 操作，可進一步簡化您的程式碼編寫。在文件模型中，主類別為 `Table` 和 `Document`。`Table` 類別提供資料操作方法，例如 `PutItem`、`GetItem` 和 `DeleteItem`。該類別也提供 `Query` 和 `Scan` 方法。`Document` 類別則代表資料表中的單一項目。

上述文件模型類別可在 `Amazon.DynamoDBv2.DocumentModel` 命名空間中取得。

**注意**  
您無法使用文件模型建立、更新和刪除資料表。但文件模型支援大部分的常見資料操作。

**Topics**
+ [支援的資料類型](#MidLevelAPILimitations.SupportedTypes)

## 支援的資料類型
<a name="MidLevelAPILimitations.SupportedTypes"></a>

文件模型會支援一組原始的 .NET 資料類型和集合資料類型。模型目前支援下列基本資料類型。
+ `bool`
+ `byte` 
+ `char`
+ `DateTime`
+ `decimal`
+ `double`
+ `float`
+ `Guid`
+ `Int16`
+ `Int32`
+ `Int64`
+ `SByte`
+ `string`
+ `UInt16`
+ `UInt32`
+ `UInt64`

下表摘要說明上述 .NET 類型與 DynamoDB 類型的映射。


****  

| .NET 基本類型 | DynamoDB 類型 | 
| --- | --- | 
|  所有數字類型  |  `N` (數字類型)  | 
|  所有字串類型  |  `S` (字串類型)   | 
|  MemoryStream, byte[]  |  `B` (二進位類型)   | 
| bool | N (數字類型)。0 代表 false，1 代表 true。 | 
| DateTime | S (字串類型)。DateTime 值會以 ISO-8601 格式字串存放。 | 
| Guid | S (字串類型)。 | 
| 集合類型 (List、HashSet 和陣列) | BS (二進位集) 類型、SS (字串集) 類型和 NS (數字集) 類型。 | 

適用於 .NET 的 AWS SDK 會定義將 DynamoDB 的布林值、null 值、清單和映射類型映射到 .NET 文件模型 API 的類型：
+ 使用 `DynamoDBBool` 作為布林類型。
+ 使用 `DynamoDBNull` 作為 null 類型。
+ 使用 `DynamoDBList` 作為清單類型。
+ 使用 `Document` 作為映射類型。

**注意**  
支援空白的二進位值。
支援讀取空白字串值。寫入 DynamoDB 時，字串 Set 類型的屬性值會支援空白字串的屬性值。List 或 Map 類型中包含的字串類型的空白字串屬性值和空白字串值會從寫入請求中捨棄

# 使用 .NET 物件持久性模型和 DynamoDB
<a name="DotNetSDKHighLevel"></a>

 適用於 .NET 的 AWS SDK 提供物件持久性模型，可讓您將用戶端類別映射至 Amazon DynamoDB 資料表。然後每個物件執行個體會映射至相對應資料表中的某個項目。為了將用戶端物件儲存至資料表，物件持久性模型會提供 `DynamoDBContext` 類別 (即 DynamoDB 的進入點)。此類別可讓您連線至 DynamoDB，繼而存取資料表、執行各種 CRUD 操作以及執行查詢。

物件持久性模型提供了一組屬性，可將用戶端類別映射到資料表，並將屬性/欄位映射至資料表屬性。

**注意**  
物件持久性模型不提供用於建立、更新或刪除資料表的 API。它只提供資料操作。您只能使用 適用於 .NET 的 AWS SDK 低階 API 來建立、更新和刪除資料表。

以下範例會示範物件持久性模型的運作方式。它會從 `ProductCatalog` 資料表開始作業。它將 `Id` 作為主索引鍵。

```
ProductCatalog(Id, ...)
```

假設您的 `Book` 類別具有 `Title`、`ISBN` 以及 `Authors` 屬性。您可以透過新增物件持久性模型所定義的屬性，將 `Book` 類別映射至 `ProductCatalog` 資料表中，如下列 C\$1 程式碼範例所示。

**Example**  

```
[DynamoDBTable("ProductCatalog")]
  public class Book
  {
    [DynamoDBHashKey]
    public int Id { get; set; }

    public string Title { get; set; }
    public int ISBN { get; set; }

    [DynamoDBProperty("Authors")]
    public List<string> BookAuthors { get; set; }

    [DynamoDBIgnore]
    public string CoverPage { get; set; }
  }
```

在上述範例中，`DynamoDBTable` 屬性會將 `Book` 類別映射至 `ProductCatalog` 資料表。

物件持久性模型支援類別屬性與資料表屬性之間的明確映射和預設映射。
+ **明確映射：**若要將屬性映射至主索引鍵，您必須使用 `DynamoDBHashKey` 和 `DynamoDBRangeKey` 物件持久性模型屬性。此外，對於非主索引鍵屬性，如果類別中的屬性名稱和要對應的資料表屬性不相同，則必須明確新增 `DynamoDBProperty` 屬性來定義映射。

  在上述範例中，`Id` 屬性會映射至具有相同名稱的主索引鍵，`BookAuthors` 屬性則會映射至 `ProductCatalog` 資料表中的 `Authors` 屬性。
+ **預設映射：**依預設，物件持久性模型會將類別屬性映射至資料表中具有相同名稱的屬性。

  在上述範例中，屬性 `Title` 和 `ISBN` 會映射至 `ProductCatalog` 資料表中具有相同名稱的屬性。

您不必映射每個類別屬性。您可以新增 `DynamoDBIgnore` 屬性來識別這些屬性。當您將 `Book` 執行個體儲存至資料表時，`DynamoDBContext` 不會包含 `CoverPage` 屬性。在擷取書籍執行個體時，它也不會傳回此屬性。

您可以映射 .NET 基本類型的屬性，如 int 和字串。只要提供適當的轉換器將任意資料映射至其中一種 DynamoDB 類型，您也可以映射任意資料類型。若要進一步了解如何映射任意類型，請參閱 [使用 適用於 .NET 的 AWS SDK 物件持久性模型使用 DynamoDB 映射任意資料](DynamoDBContext.ArbitraryDataMapping.md)。

物件持久性模型支援樂觀鎖定。在更新操作期間，這可確保您擁有即將更新項目的最新副本。如需詳細資訊，請參閱[使用 DynamoDB 和 適用於 .NET 的 AWS SDK 物件持久性模型的樂觀鎖定](DynamoDBContext.VersionSupport.md)。

如需詳細資訊，請參閱下列主題。

**Topics**
+ [支援的資料類型](#DotNetDynamoDBContext.SupportedTypes)
+ [.NET 物件持久性模型的 DynamoDB 屬性](DeclarativeTagsList.md)
+ [.NET 物件持久性模型的 DynamoDBContext 類別](DotNetDynamoDBContext.md)
+ [使用 DynamoDB 和 適用於 .NET 的 AWS SDK 物件持久性模型的樂觀鎖定](DynamoDBContext.VersionSupport.md)
+ [使用 適用於 .NET 的 AWS SDK 物件持久性模型使用 DynamoDB 映射任意資料](DynamoDBContext.ArbitraryDataMapping.md)

## 支援的資料類型
<a name="DotNetDynamoDBContext.SupportedTypes"></a>

物件持久性模型會支援一組基本的 .NET 資料類型、集合和任意資料類型。模型目前支援下列基本資料類型。
+ `bool`
+ `byte` 
+ `char`
+ `DateTime`
+ `decimal`
+ `double`
+ `float`
+ `Int16`
+ `Int32`
+ `Int64`
+ `SByte`
+ `string`
+ `UInt16`
+ `UInt32`
+ `UInt64`

物件持久性模型也支援 .NET 集合類型。`DynamoDBContext` 能夠轉換具體的集合類型和簡單的純舊 CLR 物件 (POCO)。

下表摘要說明上述 .NET 類型與 DynamoDB 類型的映射。


****  

| .NET 基本類型 | DynamoDB 類型 | 
| --- | --- | 
|  所有數字類型  |  `N` (數字類型)  | 
|  所有字串類型  |  `S` (字串類型)   | 
|  MemoryStream, byte[]  |  `B` (二進位類型)   | 
| bool | N (數字類型)。0 代表 false，1 代表 true。 | 
| 集合類型 | BS (二進位集) 類型、SS (字串集) 類型和 NS (數字集) 類型。 | 
| DateTime | S (字串類型)。DateTime 值會以 ISO-8601 格式字串存放。 | 

物件持久性模型也支援任意資料類型。不過，您必須提供轉換器程式碼，才能將複雜類型映射至 DynamoDB 類型。

**注意**  
支援空白的二進位值。
支援讀取空白字串值。寫入 DynamoDB 時，字串 Set 類型的屬性值會支援空白字串的屬性值。List 或 Map 類型中包含的字串類型的空白字串屬性值和空白字串值會從寫入請求中捨棄

# .NET 物件持久性模型的 DynamoDB 屬性
<a name="DeclarativeTagsList"></a>

本節說明物件持久性模型所提供的屬性，讓您可以將類別和屬性映射至 DynamoDB 資料表和屬性。

**注意**  
在下列屬性中，只有 `DynamoDBTable` 和 `DynamoDBHashKey` 是必要屬性。

## DynamoDBGlobalSecondaryIndexHashKey
<a name="w2aac17b9c21c23c37b7"></a>

將類別屬性映射至全域次要索引的分割區索引鍵。如果您需要對全域次要索引進行 `Query`，請使用此屬性。

## DynamoDBGlobalSecondaryIndexRangeKey
<a name="w2aac17b9c21c23c37b9"></a>

將類別屬性映射至全域次要索引的排序索引鍵。如果您需要對全域次要索引進行 `Query`，並且想要使用索引的排序索引鍵來縮小您結果的範圍，請使用此屬性。

## DynamoDBHashKey
<a name="w2aac17b9c21c23c37c11"></a>

將類別屬性映射至資料表主索引鍵的分割區索引鍵。主索引鍵屬性不能是集合類型。

下列 C\$1 程式碼範例會映射 `Book` 類別至 `ProductCatalog` 資料表，並映射 `Id` 屬性至資料表主索引鍵的分割區索引鍵。

```
[DynamoDBTable("ProductCatalog")]
public class Book 
{
    [DynamoDBHashKey]
    public int Id { get; set; }

    // Additional properties go here.
}
```

## DynamoDBIgnore
<a name="w2aac17b9c21c23c37c13"></a>

指出應該忽略的相關聯屬性。如果您不想儲存任何類別屬性，可以新增此屬性來指示 `DynamoDBContext` 將物件儲存到資料表時不包含此屬性。

## DynamoDBLocalSecondaryIndexRangeKey
<a name="w2aac17b9c21c23c37c15"></a>

將類別屬性映射至本機次要索引的排序索引鍵。如果您需要對本機次要索引進行 `Query`，並且想要使用索引的排序索引鍵來縮小您結果的範圍，請使用此屬性。

## DynamoDBProperty
<a name="w2aac17b9c21c23c37c17"></a>

將類別屬性映射至資料表屬性。如果類別屬性映射至具有相同名稱的資料表屬性，則不需要指定此屬性。不過，如果名稱不同，您可以使用此標籤提供映射。在下列 C\$1 陳述式中，`DynamoDBProperty` 會將 `BookAuthors` 屬性映射至資料表中的 `Authors` 屬性。

```
[DynamoDBProperty("Authors")]
public List<string> BookAuthors { get; set; }
```

當儲存物件資料至相應的資料表時，`DynamoDBContext` 會使用此映射資訊來建立 `Authors` 屬性。

## DynamoDBRenamable
<a name="w2aac17b9c21c23c37c19"></a>

指定類別屬性的替代名稱。如果您正在撰寫自訂轉換器，以將任意資料映射至 DynamoDB 資料表 (其中類別屬性的名稱與資料表屬性不同)，則此功能非常有用。

## DynamoDBRangeKey
<a name="w2aac17b9c21c23c37c21"></a>

將類別屬性映射至資料表主索引鍵的排序索引鍵。如果資料表具有複合主鍵 (分割區索引鍵和排序索引鍵)，則必須在類別映射中同時指定 `DynamoDBHashKey` 和 `DynamoDBRangeKey` 屬性。

例如，範例資料表 `Reply` 有一個由 `Id` 分割區索引鍵和 `Replenishment` 排序索引鍵組成的主索引鍵。下列 C\$1 程式碼範例將 `Reply` 類別映射至 `Reply` 資料表。類別定義也會指出其中兩個屬性映射至主索引鍵。

```
[DynamoDBTable("Reply")]
public class Reply 
{
   [DynamoDBHashKey]
   public int ThreadId { get; set; }
   [DynamoDBRangeKey]
   public string Replenishment { get; set; }
   
   // Additional properties go here.
}
```

## DynamoDBTable
<a name="w2aac17b9c21c23c37c23"></a>

識別 DynamoDB 中類別要映射的目標資料表。例如，下列 C\$1 程式碼範例將 `Developer` 類別映射至 DynamoDB 中的 `People` 資料表。

```
[DynamoDBTable("People")]
public class Developer { ...}
```

此屬性可被繼承或覆寫。
+ `DynamoDBTable` 屬性可被繼承。在上述範例中，如果新增新從 `Developer` 類別繼承的新類別 `Lead`，它也會映射至 `People` 資料表。`Developer` 和 `Lead` 物件都存放在 `People` 資料表中。
+ `DynamoDBTable` 屬性也可被寫。在下列 C\$1 程式碼範例中，`Manager` 類別繼承自 `Developer` 類別。但是，明確新增 `DynamoDBTable` 屬性會將類別映射到另一個資料表 (`Managers`)。

  ```
  [DynamoDBTable("Managers")]
  public class Manager : Developer { ...}
  ```

 您可以新增選用參數 `LowerCamelCaseProperties`，以便請求 DynamoDB 在儲存物件至資料表時，將屬性名稱的第一個字母變成小寫，如下列 C\$1 範例所示。

```
[DynamoDBTable("People", LowerCamelCaseProperties=true)]
public class Developer 
{
    string DeveloperName;
    ...
}
```

在儲存 `Developer` 類別的執行個體時，`DynamoDBContext` 會儲存 `DeveloperName` 屬性作為 `developerName`。

## DynamoDBVersion
<a name="w2aac17b9c21c23c37c25"></a>

標識用於儲存項目版本編號的類別屬性。如需版本控制的詳細資訊，請參閱「[使用 DynamoDB 和 適用於 .NET 的 AWS SDK 物件持久性模型的樂觀鎖定](DynamoDBContext.VersionSupport.md)」。

# .NET 物件持久性模型的 DynamoDBContext 類別
<a name="DotNetDynamoDBContext"></a>

`DynamoDBContext` 類別是 Amazon DynamoDB 資料庫的進入點。它可讓您連線至 DynamoDB，繼而存取各種資料表中的資料、執行各種 CRUD 操作以及執行查詢。此 `DynamoDBContext` 類別提供下列方法。

**Topics**
+ [Create​MultiTable​BatchGet](#w2aac17b9c21c23c39b7)
+ [Create​MultiTable​BatchWrite](#w2aac17b9c21c23c39b9)
+ [CreateBatchGet](#w2aac17b9c21c23c39c11)
+ [CreateBatchWrite](#w2aac17b9c21c23c39c13)
+ [刪除](#w2aac17b9c21c23c39c15)
+ [Dispose](#w2aac17b9c21c23c39c17)
+ [Execute​Batch​Get](#w2aac17b9c21c23c39c19)
+ [Execute​Batch​Write](#w2aac17b9c21c23c39c21)
+ [FromDocument](#w2aac17b9c21c23c39c23)
+ [FromQuery](#w2aac17b9c21c23c39c25)
+ [FromScan](#w2aac17b9c21c23c39c27)
+ [Get​Target​Table](#w2aac17b9c21c23c39c29)
+ [Load](#w2aac17b9c21c23c39c31)
+ [Query](#w2aac17b9c21c23c39c33)
+ [Save](#w2aac17b9c21c23c39c35)
+ [Scan](#w2aac17b9c21c23c39c37)
+ [ToDocument](#w2aac17b9c21c23c39c39)
+ [指定 DynamoDBContext 的選用參數](#OptionalConfigParams)

## Create​MultiTable​BatchGet
<a name="w2aac17b9c21c23c39b7"></a>

建立由多個個別 `BatchGet` 物件組成的 `MultiTableBatchGet` 物件。其中的每個 `BatchGet` 物件都可用來從單一 DynamoDB 資料表中擷取項目。

若要從資料表擷取項目，請使用 `ExecuteBatchGet` 方法，將 `MultiTableBatchGet` 物件作為參數傳遞。

## Create​MultiTable​BatchWrite
<a name="w2aac17b9c21c23c39b9"></a>

建立由多個個別 `BatchWrite` 物件組成的 `MultiTableBatchWrite` 物件。其中的每個 `BatchWrite` 物件可用來寫入或刪除單一 DynamoDB 資料表中的項目。

若要寫入資料表，請使用 `ExecuteBatchWrite` 方法，將 `MultiTableBatchWrite` 物件作為參數傳遞。

## CreateBatchGet
<a name="w2aac17b9c21c23c39c11"></a>

建立 `BatchGet` 物件，您可以使用該物件從資料表中擷取多個項目。

## CreateBatchWrite
<a name="w2aac17b9c21c23c39c13"></a>

建立 `BatchWrite` 物件，您可以使用該物件將多個項目放入資料表中，或從資料表中刪除多個項目。

## 刪除
<a name="w2aac17b9c21c23c39c15"></a>

刪除資料表中的項目。這個方法需要您希望刪除之項目的主索引鍵。您可以提供主索引鍵值或包含主索引鍵值的用戶端物件，作為此方法的參數。
+ 如果指定用戶端物件作為參數，且已啟用樂觀鎖定，則只有在物件的用戶端和伺服器端版本相符時，才能成功刪除項目。
+ 如果只指定主索引鍵值作為參數，無論您是否已啟用樂觀鎖定，刪除都會成功。

**注意**  
若要在背景執行此操作，請改用 `DeleteAsync` 方法。

## Dispose
<a name="w2aac17b9c21c23c39c17"></a>

處置所有受管和非受管的資源。

## Execute​Batch​Get
<a name="w2aac17b9c21c23c39c19"></a>

從一或多個資料表讀取資料，處理 `MultiTableBatchGet` 中的所有 `BatchGet` 物件。

**注意**  
若要在背景執行此操作，請改用 `ExecuteBatchGetAsync` 方法。

## Execute​Batch​Write
<a name="w2aac17b9c21c23c39c21"></a>

在一或多個資料表中寫入或刪除資料，處理 `MultiTableBatchWrite` 中的所有 `BatchWrite` 物件。

**注意**  
若要在背景執行此操作，請改用 `ExecuteBatchWriteAsync` 方法。

## FromDocument
<a name="w2aac17b9c21c23c39c23"></a>

若為 `Document` 執行個體，`FromDocument` 方法會傳回用戶端類別的執行個體。

如果您想使用文件模型類別以及物件持久性模型來執行任何資料操作，這會很有幫助。如需 提供之文件模型類別的詳細資訊 適用於 .NET 的 AWS SDK，請參閱 [在 DynamoDB 中使用 .NET 文件模型](DotNetSDKMidLevel.md)。

假設您有名為 `doc` 的 `Document` 物件，且其中包含 `Forum` 項目的表示法。(若要查看如何建構此物件，請參閱本主題後續內容中的 `ToDocument` 方法說明。) 您可以使用 `FromDocument` 從 `Document` 擷取 `Forum` 項目，如下列 C\$1 程式碼範例所示。

**Example**  

```
forum101 = context.FromDocument<Forum>(101);
```

**注意**  
如果您的 `Document` 物件會實作 `IEnumerable` 介面，您可以使用 `FromDocuments` 方法。這允許您逐一查看 `Document` 中的所有類別執行個體。

## FromQuery
<a name="w2aac17b9c21c23c39c25"></a>

以 `QueryOperationConfig` 物件中定義的查詢參數執行 `Query` 操作。

**注意**  
若要在背景執行此操作，請改用 `FromQueryAsync` 方法。

## FromScan
<a name="w2aac17b9c21c23c39c27"></a>

以 `ScanOperationConfig` 物件中定義的掃描參數執行 `Scan` 操作。

**注意**  
若要在背景執行此操作，請改用 `FromScanAsync` 方法。

## Get​Target​Table
<a name="w2aac17b9c21c23c39c29"></a>

擷取指定類型的目標資料表。如果您正在撰寫自訂轉換器，將任意資料映射至 DynamoDB 資料表，而且需要判斷哪個資料表與自訂資料類型相關聯，則此功能非常有用。

## Load
<a name="w2aac17b9c21c23c39c31"></a>

從資料表擷取項目。這個方法只需要您希望擷取之項目的主索引鍵。

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

`Load` 或 `LoadAsync` 方法會呼叫 [GetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) 操作，這需要您指定資料表的主索引鍵。由於 `GetItem` 會忽略 `IndexName` 參數，您無法使用索引分割區或排序索引鍵載入項目。因此您必須使用資料表主索引鍵來載入項目。

**注意**  
若要在背景執行此操作，請改用 `LoadAsync` 方法。若要檢視使用 `LoadAsync` 方法在 DynamoDB 資料表執行高階 CRUD 操作的範例，請參閱下列範例。

```
    /// <summary>
    /// Shows how to perform high-level CRUD operations on an Amazon DynamoDB
    /// table.
    /// </summary>
    public class HighLevelItemCrud
    {
        public static async Task Main()
        {
            var client = new AmazonDynamoDBClient();
            DynamoDBContext context = new DynamoDBContext(client);
            await PerformCRUDOperations(context);
        }

        public static async Task PerformCRUDOperations(IDynamoDBContext context)
        {
            int bookId = 1001; // Some unique value.
            Book myBook = new Book
            {
                Id = bookId,
                Title = "object persistence-AWS SDK for.NET SDK-Book 1001",
                Isbn = "111-1111111001",
                BookAuthors = new List<string> { "Author 1", "Author 2" },
            };

            // Save the book to the ProductCatalog table.
            await context.SaveAsync(myBook);

            // Retrieve the book from the ProductCatalog table.
            Book bookRetrieved = await context.LoadAsync<Book>(bookId);

            // Update some properties.
            bookRetrieved.Isbn = "222-2222221001";

            // Update existing authors list with the following values.
            bookRetrieved.BookAuthors = new List<string> { " Author 1", "Author x" };
            await context.SaveAsync(bookRetrieved);

            // Retrieve the updated book. This time, add the optional
            // ConsistentRead parameter using DynamoDBContextConfig object.
            await context.LoadAsync<Book>(bookId, new DynamoDBContextConfig
            {
                ConsistentRead = true,
            });

            // Delete the book.
            await context.DeleteAsync<Book>(bookId);

            // Try to retrieve deleted book. It should return null.
            Book deletedBook = await context.LoadAsync<Book>(bookId, new DynamoDBContextConfig
            {
                ConsistentRead = true,
            });

            if (deletedBook == null)
            {
                Console.WriteLine("Book is deleted");
            }
        }
    }
```

## Query
<a name="w2aac17b9c21c23c39c33"></a>

根據您提供的查詢參數查詢資料表。

您只能查詢具有複合主鍵 (分割區索引鍵和排序索引鍵) 的資料表。查詢時，必須指定分割區索引鍵和套用至排序索引鍵的條件。

假設您有用戶端 `Reply` 類別映射至 DynamoDB 中的 `Reply` 資料表。下列 C\$1 程式碼範例會查詢 `Reply` 資料表，找出過去 15 天所張貼的論壇主題回覆。`Reply` 資料表的主索引鍵具有 `Id` 分割區索引鍵和 `ReplyDateTime` 排序索引鍵。

**Example**  

```
DynamoDBContext context = new DynamoDBContext(client);

string replyId = "DynamoDB#DynamoDB Thread 1"; //Partition key
DateTime twoWeeksAgoDate = DateTime.UtcNow.Subtract(new TimeSpan(14, 0, 0, 0)); // Date to compare.
IEnumerable<Reply> latestReplies = context.Query<Reply>(replyId, QueryOperator.GreaterThan, twoWeeksAgoDate);
```

這會傳回 `Reply` 物件的集合。

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

如果資料表具有簡易主索引鍵 (分割區索引鍵)，您便不能使用 `Query` 方法。不過，您可以使用 `Load` 方法並提供分割區索引鍵來擷取項目。

**注意**  
若要在背景執行此操作，請改用 `QueryAsync` 方法。

## Save
<a name="w2aac17b9c21c23c39c35"></a>

將指定的物件儲存至資料表。如果輸入物件中指定的主索引鍵不存在於資料表中，該方法會將新項目新增至資料表中。如果主索引鍵存在，該方法會更新現有項目。

如果您已設定樂觀鎖定，則只有在用戶端和項目的伺服器端版本相符時才能成功更新項目。如需詳細資訊，請參閱[使用 DynamoDB 和 適用於 .NET 的 AWS SDK 物件持久性模型的樂觀鎖定](DynamoDBContext.VersionSupport.md)。

**注意**  
若要在背景執行此操作，請改用 `SaveAsync` 方法。

## Scan
<a name="w2aac17b9c21c23c39c37"></a>

執行整個資料表掃描。

您可以指定掃描條件來篩選掃描結果。您可以根據資料表中的任何屬性來評估條件。假設您有用戶端 `Book` 類別映射至 DynamoDB 中的 `ProductCatalog` 資料表。下列 C\$1 範例會掃描資料表，並且只會傳回價格低於 0 的所有書籍項目。

**Example**  

```
IEnumerable<Book> itemsWithWrongPrice = context.Scan<Book>(
                    new ScanCondition("Price", ScanOperator.LessThan, price),
                    new ScanCondition("ProductCategory", ScanOperator.Equal, "Book")
      );
```

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

出於效能考量，您應查詢資料表並避免執行資料表掃描。

**注意**  
若要在背景執行此操作，請改用 `ScanAsync` 方法。

## ToDocument
<a name="w2aac17b9c21c23c39c39"></a>

從類別執行個體傳回 `Document` 文件模型類別的執行個體。

如果您想使用文件模型類別以及物件持久性模型來執行任何資料操作，這會很有幫助。如需 提供之文件模型類別的詳細資訊 適用於 .NET 的 AWS SDK，請參閱 [在 DynamoDB 中使用 .NET 文件模型](DotNetSDKMidLevel.md)。

假設您有用戶端類別映射至範例 `Forum` 資料表。然後，您可以使用 `DynamoDBContext` 從 `Forum` 資料表中獲取項目作為 `Document` 物件，如下列 C\$1 程式碼範例所示。

**Example**  

```
DynamoDBContext context = new DynamoDBContext(client);

Forum forum101 = context.Load<Forum>(101); // Retrieve a forum by primary key.
Document doc = context.ToDocument<Forum>(forum101);
```

## 指定 DynamoDBContext 的選用參數
<a name="OptionalConfigParams"></a>

使用物件持久性模型時，您可以指定 `DynamoDBContext` 的下列選用參數。
+ **`ConsistentRead`：**當使用 `Load`、`Query` 或 `Scan` 操作來擷取資料時，您可以新增此選用參數來請求資料的最新數值。
+ **`IgnoreNullValues`：**此參數會通知 `DynamoDBContext` 在 `Save` 操作期間忽略屬性上的 Null 數值。如果此參數為 false (或未設定)，則會將 Null 數值轉譯為刪除特定屬性的指令。
+ **`SkipVersionCheck`：**此參數會通知 `DynamoDBContext` 不要在儲存或刪除項目時比較版本。如需版本控制的詳細資訊，請參閱「[使用 DynamoDB 和 適用於 .NET 的 AWS SDK 物件持久性模型的樂觀鎖定](DynamoDBContext.VersionSupport.md)」。
+ **`TableNamePrefix`：**使用特定字串作為所有資料表名稱的字首。如果此參數為 null (或未設定)，則不會使用字首。
+ `DynamoDBEntryConversion` – 指定用戶端使用的轉換結構描述。您可以將此參數設定為版本 V1 或 V2。V1 是預設版本。

  根據您設定的版本，此參數的行為會變更。例如：
  + 在 V1 中，`bool` 資料類型會轉換為 `N` 數字類型，其中 0 代表 false，1 代表 true。在 V2 中，`bool` 會轉換為 `BOOL`。
  + 在 V2 中，清單和陣列不會與 HashSet 一起分組。數值、字串類型和二進位類型的清單和陣列會轉換為 `L` (清單) 類型，可以傳送空白清單來更新清單。這與 V1 不同，其中空白清單不會透過線路傳送。

    在 V1 中，清單、HashSet 和陣列等集合類型都視為相同。清單、HashSet 和數值陣列會轉換為 `NS` (數字集) 類型。

  下列範例會將轉換結構描述版本設定為 V2，變更 .NET 類型和 DynamoDB 資料類型之間的轉換行為。

  ```
  var config = new DynamoDBContextConfig
  {
      Conversion = DynamoDBEntryConversion.V2
  };
  var contextV2 = new DynamoDBContext(client, config);
  ```

下列 C\$1 範例會指定 `ConsistentRead` 和 `SkipVersionCheck` 這兩個上述選用參數來建立新的 `DynamoDBContext`。

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
...
DynamoDBContext context =
       new DynamoDBContext(client, new DynamoDBContextConfig { ConsistentRead = true, SkipVersionCheck = true});
```

`DynamoDBContext` 包含這些選用參數，以及您使用此內容傳送的每個請求。

您可以使用 `DynamoDBContext` 為個別操作指定參數，而不是在 `DynamoDBContext` 層級設定這些參數，如下列 C\$1 程式碼範例所示。此範例會載入特定的書籍項目。`DynamoDBContext` 的 `Load` 方法會指定 `ConsistentRead` 和 `SkipVersionCheck` 等選用參數。

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
...
DynamoDBContext context = new DynamoDBContext(client);
Book bookItem = context.Load<Book>(productId,new DynamoDBContextConfig{ ConsistentRead = true, SkipVersionCheck = true });
```

在此例中，`DynamoDBContext` 只有在傳送 `Get` 請求時才會包含這些參數。

# 使用 DynamoDB 和 適用於 .NET 的 AWS SDK 物件持久性模型的樂觀鎖定
<a name="DynamoDBContext.VersionSupport"></a>

物件持久性模型中的樂觀鎖定支援可確保應用程式的項目版本與伺服器端的項目版本相同，然後再更新或刪除項目。假設您要擷取待更新的項目。不過，在您傳回更新之前，某些其他應用程式會更新相同的項目。現在應用程式的項目有過時的副本。如果沒有樂觀鎖定，您執行的任何更新都會覆寫其他應用程式所做的更新。

物件持久性模型的樂觀鎖定功能提供了 `DynamoDBVersion` 標籤，可讓您用來啟用樂觀鎖定。若要使用此功能，請在類別中新增一項屬性，以便儲存版本編號。您可以將 `DynamoDBVersion` 屬性加入該屬性。當您第一次儲存物件時，`DynamoDBContext` 會指派版本編號，並在每次更新項目時遞增值。

只有在用戶端物件版本與伺服器端項目的對應版本編號相符時，您的更新或刪除請求才會成功。如果應用程式有過時的副本，它必須先從伺服器取得最新版本，才能更新或刪除該項目。

下列 C\$1 程式碼範例會定義 `Book` 類別，該類別具有將其映射至 `ProductCatalog` 資料表的物件持久性屬性。類別中的 `VersionNumber` 屬性裝飾了會儲存版本編號數值的 `DynamoDBVersion` 屬性。

**Example**  

```
[DynamoDBTable("ProductCatalog")]
  public class Book
  {
    [DynamoDBHashKey]   //Partition key
    public int Id { get; set; }
    [DynamoDBProperty]
    public string Title { get; set; }
    [DynamoDBProperty]
    public string ISBN { get; set; }
    [DynamoDBProperty("Authors")]
    public List<string> BookAuthors { get; set; }
    [DynamoDBVersion]
    public int? VersionNumber { get; set; }
  }
```

**注意**  
您只可將 `DynamoDBVersion` 屬性套用至可為 null 的數字基本類型 (如 `int?`)。

樂觀鎖定對 `DynamoDBContext` 操作的影響如下：
+ 對於新項目，`DynamoDBContext` 會指派初始版本編號 0。如果您擷取現有項目，請更新其一或多個屬性並嘗試儲存變更，只有在用戶端的版本編號與伺服器端的相符時，儲存操作才會成功。`DynamoDBContext` 會遞增版本號碼。您不需要設定版本編號。
+ `Delete` 方法提供可將主索引鍵值或物件作為參數的多載，如下列 C\$1 程式碼範例所示。  
**Example**  

  ```
  DynamoDBContext context = new DynamoDBContext(client);
  ...
  // Load a book.
  Book book = context.Load<ProductCatalog>(111);
  // Do other operations.
  // Delete 1 - Pass in the book object.
  context.Delete<ProductCatalog>(book);
  
  // Delete 2 - Pass in the Id (primary key)
  context.Delete<ProductCatalog>(222);
  ```

  如果提供物件作為參數，則只有在物件版本符合對應的伺服器端項目版本時才能成功刪除。不過，如果提供主索引鍵值作為參數，`DynamoDBContext` 不知道任何版本編號，其會在沒有檢查是哪個版本的情況下刪除項目。

  請注意，物件持久性模型程式碼中的樂觀鎖定內部實作會使用 DynamoDB 中的條件式更新和條件式刪除 API 動作。

## 停用樂觀鎖定
<a name="DotNetDynamoDBContext.DisablingOptimisticLocking"></a>

若要停用樂觀鎖定，您可以使用 `SkipVersionCheck` 組態屬性。您可以在建立 `DynamoDBContext` 時設定此屬性。在這種情況下，您使用內容發起的任何請求都會停用樂觀鎖定。如需詳細資訊，請參閱[指定 DynamoDBContext 的選用參數](DotNetDynamoDBContext.md#OptionalConfigParams)。

您可以停用特定操作的樂觀鎖定，而不是在內容層級設定屬性，如下列 C\$1 程式碼範例所示。此範例會使用內容來刪除書籍項目。`Delete` 方法可設定選用 `SkipVersionCheck` 屬性為 true，停用版本檢查。

**Example**  

```
DynamoDBContext context = new DynamoDBContext(client);
// Load a book.
Book book = context.Load<ProductCatalog>(111);
...
// Delete the book.
context.Delete<Book>(book, new DynamoDBContextConfig { SkipVersionCheck = true });
```

# 使用 適用於 .NET 的 AWS SDK 物件持久性模型使用 DynamoDB 映射任意資料
<a name="DynamoDBContext.ArbitraryDataMapping"></a>

除了支援的 .NET 類型之外 (請參閱 [支援的資料類型](DotNetSDKHighLevel.md#DotNetDynamoDBContext.SupportedTypes))，您還可以使用應用程式中未直接映射至 Amazon DynamoDB 類型的類型。只要您提供轉換器將資料從任意類型轉換為 DynamoDB 類型，物件持久性模型就支援儲存任意類型的資料，反之亦然。轉換器程式碼會在物件的儲存和載入期間轉換資料。

您可以在用戶端建立任何類型。不過，存放在資料表中的資料是 DynamoDB 類型之一；在查詢和掃描期間，所做的任何資料比較都會與存放在 DynamoDB 中的資料進行比較。

下列 C\$1 程式碼範例會定義具有 `Id`、`Title`、`ISBN` 以及 `Dimension` 屬性的 `Book` 類別。`Dimension` 屬性具有 `DimensionType`，可說明 `Height`、`Width` 和 `Thickness` 屬性。範例程式碼提供了轉換器方法 `ToEntry` 和 `FromEntry` 來轉換 `DimensionType` 與 DynamoDB 字串類型之間的資料。例如，在儲存 `Book` 執行個體時，轉換器會建立一個書籍 `Dimension` 字串，例如 "8.5x11x.05"。在擷取書籍時，它會將字串轉換為 `DimensionType` 執行個體。

此範例會將 `Book` 類型映射為 `ProductCatalog` 資料表。它儲存了一個範例 `Book` 執行個體、擷取、更新其維度並再次儲存更新的 `Book`。



如需測試下列範例的逐步說明，請參閱 [.NET 程式碼範例](CodeSamples.DotNet.md)。

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
    class HighLevelMappingArbitraryData
    {
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                DynamoDBContext context = new DynamoDBContext(client);

                // 1. Create a book.
                DimensionType myBookDimensions = new DimensionType()
                {
                    Length = 8M,
                    Height = 11M,
                    Thickness = 0.5M
                };

                Book myBook = new Book
                {
                    Id = 501,
                    Title = "AWS SDK for .NET Object Persistence Model Handling Arbitrary Data",
                    ISBN = "999-9999999999",
                    BookAuthors = new List<string> { "Author 1", "Author 2" },
                    Dimensions = myBookDimensions
                };

                context.Save(myBook);

                // 2. Retrieve the book.
                Book bookRetrieved = context.Load<Book>(501);

                // 3. Update property (book dimensions).
                bookRetrieved.Dimensions.Height += 1;
                bookRetrieved.Dimensions.Length += 1;
                bookRetrieved.Dimensions.Thickness += 0.2M;
                // Update the book.
                context.Save(bookRetrieved);

                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }
        }
    }
    [DynamoDBTable("ProductCatalog")]
    public class Book
    {
        [DynamoDBHashKey] //Partition key
        public int Id
        {
            get; set;
        }
        [DynamoDBProperty]
        public string Title
        {
            get; set;
        }
        [DynamoDBProperty]
        public string ISBN
        {
            get; set;
        }
        // Multi-valued (set type) attribute.
        [DynamoDBProperty("Authors")]
        public List<string> BookAuthors
        {
            get; set;
        }
        // Arbitrary type, with a converter to map it to DynamoDB type.
        [DynamoDBProperty(typeof(DimensionTypeConverter))]
        public DimensionType Dimensions
        {
            get; set;
        }
    }

    public class DimensionType
    {
        public decimal Length
        {
            get; set;
        }
        public decimal Height
        {
            get; set;
        }
        public decimal Thickness
        {
            get; set;
        }
    }

    // Converts the complex type DimensionType to string and vice-versa.
    public class DimensionTypeConverter : IPropertyConverter
    {
        public DynamoDBEntry ToEntry(object value)
        {
            DimensionType bookDimensions = value as DimensionType;
            if (bookDimensions == null) throw new ArgumentOutOfRangeException();

            string data = string.Format("{1}{0}{2}{0}{3}", " x ",
                            bookDimensions.Length, bookDimensions.Height, bookDimensions.Thickness);

            DynamoDBEntry entry = new Primitive
            {
                Value = data
            };
            return entry;
        }

        public object FromEntry(DynamoDBEntry entry)
        {
            Primitive primitive = entry as Primitive;
            if (primitive == null || !(primitive.Value is String) || string.IsNullOrEmpty((string)primitive.Value))
                throw new ArgumentOutOfRangeException();

            string[] data = ((string)(primitive.Value)).Split(new string[] { " x " }, StringSplitOptions.None);
            if (data.Length != 3) throw new ArgumentOutOfRangeException();

            DimensionType complexData = new DimensionType
            {
                Length = Convert.ToDecimal(data[0]),
                Height = Convert.ToDecimal(data[1]),
                Thickness = Convert.ToDecimal(data[2])
            };
            return complexData;
        }
    }
}
```