

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

**注記**  
SDK for Java には、1.x と 2.x の 2 つのバージョンがあります。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 を使用することを強くお勧めします。

AWS SDK for Java には `DynamoDBMapper` クラスが用意されているため、クライアント側のクラスを Amazon DynamoDB テーブルにマッピングできます。`DynamoDBMapper` を使用するには、DynamoDB テーブル内の項目と、それが対応するコード内のオブジェクトインスタンスの間での関係性を定義します。`DynamoDBMapper` クラスを使用すると、項目に対する作成、読み込み、更新、削除 (CRUD) の各オペレーションの実行、およびテーブルに対するクエリやスキャンを行うことができます。

**Topics**
+ [DynamoDBMapper クラス](DynamoDBMapper.Methods.md)
+ [DynamoDBMapper for Java でサポートされるデータ型](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`クラスでは、テーブルを作成、更新、または削除することはできません。これらのタスクを実行するには、代わりに SDK for Java の下位レベルインターフェイスを使用します。

SDK for Java には、クラスをテーブルにマッピングするための、一連のアノテーションタイプが用意されています。たとえば、パーティションキーとして `ProductCatalog` を含む `Id` テーブルがあるとします。

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

次の Java コードに示すように、クライアントアプリケーション内のクラスを `ProductCatalog` テーブルにマッピングすることができます。このコードでは、`CatalogItem` という名前の Plain Old Java Object (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 クラス
<a name="DynamoDBMapper.Methods"></a>



`DynamoDBMapper` クラスは、Amazon DynamoDB のエントリポイントとなります。このクラスは、DynamoDB エンドポイントへのアクセスを提供し、さまざまなテーブルのデータを使用できるようにします。また、アイテムに対する作成、読み込み、更新、削除 (CRUD) の各オペレーションの実行、およびテーブルに対するクエリやスキャンを行うことができます。このクラスでは、DynamoDB を操作するために以下のメソッドが提供されます。

対応する Javadoc ドキュメントについては、*AWS SDK for Java 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)
+ [削除](#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)
+ [バッチ書き込み](#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` オブジェクトを使用して、オプションの設定パラメータを入力できます。

同じプライマリキーを持つ項目が存在しない場合は、このメソッドによってテーブル内に新しい項目が作成されます。同じプライマリキーを持つ項目が存在する場合は、その既存の項目が更新されます。パーティションキーとソートキーが String 型で、`@DynamoDBAutoGeneratedKey` によって注釈が付けられている場合、初期化しなければ、ランダムな UUID (Universally Unique Identifier) が与えられます。`@DynamoDBVersionAttribute` で注釈が付けられたバージョンフィールドは、バージョンが 1 ずつ増えていきます。さらに、バージョンフィールドが更新されるかキーが生成されると、オペレーションの結果として、渡されたオブジェクトが更新されます。

デフォルトでは、マップされたクラスプロパティに対応する属性のみが更新されます。アイテムのその他の既存の属性には影響はありません。ただし、`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)」を参照してください。

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

テーブルから項目を削除します。マッピングされたクラスのオブジェクトインスタンスを渡す必要があります。

バージョニングを有効にした場合は、クライアント側とサーバー側で項目のバージョンが一致する必要があります。ただし、`SaveBehavior.CLOBBER` オプションを使用する場合は、バージョンを一致させる必要はありません。バージョニングの詳細については、「[DynamoDB およびバージョン番号を使用した楽観的ロック](DynamoDBMapper.OptimisticLocking.md)」を参照してください。

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

テーブルまたはセカンダリインデックスをクエリする

フォーラムスレッドの返信を格納する `Reply` というテーブルがあるとします。各スレッドの件名については、0 以上の返信を受け取ることができます。`Reply` テーブルのプライマリキーは、`Id` および `ReplyDateTime` フィールドで構成されます。ここで、`Id` はプライマリキーのパーティションキー、`ReplyDateTime` はソートキーを表します。

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

`Reply` クラスと、それに対応する DynamoDB 内の `Reply` テーブルの間で、マッピングを作成したとします。次の Java コードでは、`DynamoDBMapper` を使用して特定のスレッド件名に対する過去 2 週間のすべての返信を検索しています。

**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` メソッドによって、「遅延ロード」されたコレクションが返されます。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一致するすべての項目を取得するには、`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>

テーブルまたはセカンダリインデックスのクエリを実行し、一致した結果を 1 ページ返します。`query` メソッドと同様、パーティションキー値とソートキー属性に適用されるクエリフィルタを指定する必要があります。ただし `queryPage` では、データの最初の "ページ"、つまり 1 MB 以内に収まるデータ量のみが返されます。

## スキャン
<a name="DynamoDBMapper.Methods.scan"></a>

テーブル全体またはセカンダリインデックスをスキャンします。オプションで `FilterExpression` を指定して結果セットをフィルタリングできます。

フォーラムスレッドの返信を格納する `Reply` というテーブルがあるとします。各スレッドの件名については、0 以上の返信を受け取ることができます。`Reply` テーブルのプライマリキーは、`Id` および `ReplyDateTime` フィールドで構成されます。ここで、`Id` はプライマリキーのパーティションキー、`ReplyDateTime` はソートキーを表します。

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

`Reply` テーブルに Java クラスをマッピングした場合は、`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` メソッドによって、「遅延ロード」されたコレクションが返されます。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一致するすべての項目を取得するには、`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>

テーブルまたはセカンダリインデックスがスキャンされ、一致する結果が 1 ページ返されます。`scan` メソッドと同様に、オプションで `FilterExpression` を指定して結果セットをフィルタリングできます。ただし、`scanPage` では、データの最初の "ページ"、つまり、1 MB 以内に収まるデータ量のみが返されます。

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

テーブル全体、またはセカンダリインデックスの並列スキャンが実行されます。テーブルの論理セグメントの数と、結果をフィルタするスキャン式を指定します。`parallelScan` では、スキャンタスクが複数のワーカーに分割され、論理セグメントごとに 1 つのワーカーが割り当てられます。ワーカーは、データを並列に処理し、結果を返します。

次の 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` メソッドに対する 1 つ以上の呼び出しを使用して、1 つ以上のテーブルにオブジェクトを保存します。このメソッドでは、トランザクション保証はなされません。

次の Java コードでは、2 つの項目 (書籍) を `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>

テーブルのプライマリキーを使用して、1 つ以上のテーブルから複数の項目を取り出します。

次の Java コードでは、2 つの異なるテーブルから 2 つの項目を取得します。

```
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` メソッドに対する 1 つ以上の呼び出しを使用して、1 つ以上のテーブルからオブジェクトを削除します。このメソッドでは、トランザクション保証はなされません。

次の Java コードでは、2 つの項目 (書籍) を `ProductCatalog` テーブルから削除します。

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

## バッチ書き込み
<a name="DynamoDBMapper.Methods.batchWrite"></a>

`AmazonDynamoDB.batchWriteItem` メソッドに対する 1 つ以上の呼び出しを使用して、1 つ以上のテーブルに対してオブジェクトの保存および削除を行います。このメソッドではトランザクション保証はなされず、バージョニング（条件付き入力または削除）もサポートされません。

次の 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` メソッドに対する 1 回の呼び出しを使用して、1 つまたは複数のテーブルに対してオブジェクトの保存および削除を行います。

トランザクション固有の例外のリストについては、「[TransactWriteItems エラー](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html#API_TransactWriteItems_Errors)」を参照してください。

DynamoDB トランザクション、および提供されるアトミック性、整合性、分離、耐久性 (ACID) の保証の詳細については、「[DynamoDB トランザクションで複雑なワークフローを管理する](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` メソッドへの 1 回の呼び出しを使用して、1 つまたは複数のテーブルからオブジェクトをロードします。

トランザクション固有の例外のリストについては、「[TransactGetItems エラー](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html#API_TransactGetItems_Errors)」を参照してください。

DynamoDB トランザクション、および提供されるアトミック性、整合性、分離、耐久性 (ACID) の保証の詳細については、「[DynamoDB トランザクションで複雑なワークフローを管理する](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 メソッドを `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>

Amazon S3 にアクセスする際の基盤となる `S3ClientCache` を返します。`S3ClientCache` は、`AmazonS3Client` オブジェクトのスマートマップです。複数のクライアントがある場合、`S3ClientCache` によって、AWS リージョン別にクライアントを整理しやすくなり、新しい Amazon S3 クライアントをオンデマンドで作成できるようになります。

# DynamoDBMapper for Java でサポートされるデータ型
<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 でサポートされます。  
AWS SDK for Java 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`（数値型）  | 
|  文字列  |  `S` (文字列型)   | 
|  Boolean  |  `BOOL` (ブール型)、0 または 1。  | 
|  ByteBuffer  |  `B`（バイナリ型）  | 
|  日付  |  `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 ドキュメントについては、[AWS SDK for Java 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>

テーブルの属性にプロパティをマッピングします。デフォルトでは、各クラスのプロパティが、同じ名前の項目属性にマッピングされます。ただし名前が同じでない場合は、この注釈を使用して属性にプロパティをマッピングすることができます。次の 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) が生成されます。String プロパティには、自動生成済みのキーとしてマーキングできます。

次の例は、自動生成されたパラメータを使用する方法を示しています。

```
@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 属性にマッピングしたい場合を考えます。次のサンプルコードでは、マップ型の入れ子の属性 (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` クラスを定義し、その `Id` プロパティを `ProductCatalog` タグを使用して `@DynamoDBHashKey` テーブルのプライマリキーにマッピングしています。

```
@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` クラスから継承したクラスを作成した場合には、次の Java サンプルコードに示すように、`@DynamoDBTable` 注釈を追加することで、別のテーブルに明示的にマッピングできます。

```
@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);
```

詳細については、[AWS SDK for Java 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` – リストからの読み込みに Iterator のみを使用することができます。反復中、リストは、前のすべての結果をクリアしてから、次のページをロードすることで、最大 1 ページのロードされた結果をメモリに維持するようにします。つまり、リストを反復できるのは 1 回だけです。メモリのオーバーヘッドを低減するために、大きい項目を処理するときにこの方法を使用することをお勧めします。

  マッパーインスタンスにページ分割ロードの方法を指定しない場合、デフォルトは `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 の項目を確実に同じになるようにするための手段です。この方法を使用すると、データベースの書き込みは、他のユーザーの書き込みによって上書きされないように保護されます。逆の場合も同様に保護されます。

オプティミスティックロックを使用する場合、各項目には、バージョン番号として機能する属性があります。項目をテーブルから取り出すと、アプリケーションは、その項目のバージョン番号を記録します。サーバー側のバージョン番号が変更されていない場合のみ、項目を更新できます。バージョンの不一致がある場合は、前に他のユーザーによってそのアイテムが変更されたことを意味します。アイテムの古いバージョンがあるため、更新の試行は失敗します。その場合は更新をやり直します。もう一度項目を取得して、更新してください。オプティミスティックロックでは、他のユーザーが行った変更を誤って上書きできないようにします。また、お客様が行った変更を他のユーザーが誤って変更することを防ぐこともできます。

独自の楽観的ロック戦略を実装することもできますが、AWS SDK for Java には `@DynamoDBVersionAttribute` アノテーションが用意されています。テーブルのマッピングクラスで、バージョン番号を保存する 1 つのプロパティを指定し、この注釈を使用してそのプロパティをマーキングします。オブジェクトを保存すると、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` 注釈は、`Long` や `Integer` などの、null が許容された型を提供するプリミティブラッパークラスによって得られた、null が許容された型に適用できます。

オプティミスティックロックは、次の `DynamoDBMapper` メソッドに対して次のような影響があります。
+ `save` – `DynamoDBMapper` は、新しい項目に対して初期バージョン番号 1 を割り当てます。項目を取得し、その項目の 1 つ以上のプロパティを更新して変更を保存する場合には、クライアント側とサーバー側のバージョン番号が一致する場合のみ、保存が成功します。`DynamoDBMapper` によってバージョン番号が自動的にインクリメントされます。
+ `delete` – `delete` メソッドは 1 つのオブジェクトをパラメータとして指定し、項目を削除する前に `DynamoDBMapper` によるバージョンチェックが実行されます。バージョンチェックは、リクエスト内で `DynamoDBMapperConfig.SaveBehavior.CLOBBER` を指定して無効にすることができます。

  `DynamoDBMapper` 内のオプティミスティックロックの内部実装では、DynamoDB の条件付き更新と条件付き削除機能が使用されます。
+ `transactionWrite` —
  + `Put` – `DynamoDBMapper` は、新しい項目に対して初期バージョン番号 1 を割り当てます。項目を取得し、その項目の 1 つ以上のプロパティを更新して変更を保存する場合には、クライアント側とサーバー側のバージョン番号が一致する場合のみ、put オペレーションが成功します。`DynamoDBMapper` によってバージョン番号が自動的にインクリメントされます。
  + `Update` – `DynamoDBMapper` は、新しい項目に対して初期バージョン番号 1 を割り当てます。項目を取得し、その項目の 1 つ以上のプロパティを更新して変更を保存する場合には、クライアント側とサーバー側のバージョン番号が一致する場合のみ、更新オペレーションが成功します。`DynamoDBMapper` によってバージョン番号が自動的にインクリメントされます。
  + `Delete` – `DynamoDBMapper` は、項目を削除する前にバージョンチェックを実行します。削除オペレーションは、クライアント側とサーバー側のバージョン番号が一致する場合にのみ成功します。
  + `ConditionCheck` – `@DynamoDBVersionAttribute` アノテーションは、`ConditionCheck` オペレーションではサポートされていません。`ConditionCheck` 項目に `@DynamoDBVersionAttribute` の注釈が付いている場合、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 型 (「[DynamoDBMapper for Java でサポートされるデータ型](DynamoDBMapper.DataTypes.md)」を参照) に加えて、Amazon DynamoDB 型に直接マッピングされない、アプリケーション内の型を使用できます。これらの型をマッピングするには、複合型を DynamoDB 対応の型に (またその反対に) 変換する処理を実装し、`@DynamoDBTypeConverted` アノテーションを使用して複合型のアクセサーメソッドに注釈付けを行う必要があります。コンバーターコードは、オブジェクトが保存またはロードされるときにデータを変換します。これは、複合型を消費するすべてのオペレーションでも使用されます。クエリおよびスキャンオペレーションの中でデータを比較する場合、その比較は DynamoDB に格納されているデータに対して行われることにご注意ください。

たとえば、プロパティ `CatalogItem`（`Dimension` 型）を定義する、次の `DimensionType` クラスがあるとします。このプロパティには、項目の寸法として高さ、幅、厚さが格納されています。これらの項目のディメンションを DynamoDB の中に文字列 (8.5x11x.05 など) として格納しようとしている場合を考えます。次の例は、`DimensionType` オブジェクトを文字列に変換し、文字列を `DimensionType` に変換するコンバーターコードを示しています。



**注記**  
このコード例では、アカウントの DynamoDB に対し、[DynamoDB でのコード例用のテーブルの作成とデータのロード](SampleData.md) セクションの手順に従ってデータが既にロードされていることを前提としています。  
以下の例を実行するための詳しい手順については、「[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>

AWS SDK for Java には `DynamoDBMapper` クラスが用意されているため、クライアント側のクラスを DynamoDB テーブルにマッピングできます。`DynamoDBMapper` を使用するには、DynamoDB テーブル内の項目と、それが対応するコード内のオブジェクトインスタンスの間での関係性を定義します。`DynamoDBMapper` クラスを使用すると、項目に対する作成、読み込み、更新、削除 (CRUD) の各オペレーションの実行、およびテーブルに対するクエリやスキャンを行うことができます。

`DynamoDBMapper` の使用方法の詳細については、「AWS SDK for Java 1.x デベロッパーガイド」の「[AWS SDK for Java を使用する DynamoDB の例](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-dynamodb.html)」を参照してください。**