

# DynamoDB と AWS SDK を使用したプログラミング
<a name="Programming"></a>

このセクションでは、デベロッパーに関連するトピックを説明します。代わりにコードのサンプルを実行する場合は、「[このデベロッパーガイドのコード例の実行](CodeSamples.md)」を参照してください。

**注記**  
2017 年 12 月、AWS はすべての Amazon DynamoDB エンドポイントを移行し、Amazon Trust Services (ATS) が発行する、安全な証明書を使用するプロセスを開始しました。詳細については、「[DynamoDB で SSL/TLS 接続の確立に関する問題をトラブルシューティングする](ats-certs.md)」を参照してください。

**Topics**
+ [

# DynamoDB に対する AWS SDK サポートの概要
](Programming.SDKOverview.md)
+ [

# Python と Boto3 による Amazon DynamoDB のプログラミング
](programming-with-python.md)
+ [

# JavaScript による Amazon DynamoDB のプログラミング
](programming-with-javascript.md)
+ [

# AWS SDK for Java 2.x を使用した DynamoDB のプログラミング
](ProgrammingWithJava.md)
+ [

# DynamoDB でのエラー処理
](Programming.Errors.md)
+ [

# AWS SDK で DynamoDB を使用する
](sdk-general-information-section.md)

# DynamoDB に対する AWS SDK サポートの概要
<a name="Programming.SDKOverview"></a>

次の図表は、AWS SDK を使用した Amazon DynamoDB アプリケーションの、プログラミングの概要を示しています。

![\[AWS SDK で DynamoDB を使用するためのプログラミングモデル。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/SDKSupport.png)


1. 自分が使用するプログラミング言語用のための AWS SDK を使用して、アプリケーションを作成します。

1. 各 AWS SDK には、DynamoDB を操作するプログラミングインターフェイスが 1 つ以上用意されています。使用できるインターフェイスは、使用するプログラミング言語と AWS SDK によって異なります。オプションには以下が含まれます。
   + [DynamoDB で動作する低レベルインターフェイス](Programming.SDKs.Interfaces.md#Programming.SDKs.Interfaces.LowLevel)
   + [DynamoDB で動作するドキュメントインターフェイス](Programming.SDKs.Interfaces.md#Programming.SDKs.Interfaces.Document)
   + [DynamoDB で動作するオブジェクト永続性インターフェイス](Programming.SDKs.Interfaces.md#Programming.SDKs.Interfaces.Mapper)
   + [高レベルのインターフェイス](HigherLevelInterfaces.md)

1. AWS SDK は、低レベル DynamoDB API で使用する HTTP (S) リクエストを作成します。

1. AWS SDK は DynamoDB エンドポイントにリクエストを送信します。

1. DynamoDB がリクエストを実行します。リクエストが成功すると、DynamoDB は HTTP 200 レスポンスコード (OK) を返します。リクエストが失敗した場合は、DynamoDB は HTTP エラーコードとエラーメッセージを返します。

1. AWS SDK はレスポンスを処理し、アプリケーションに伝達します。

各 AWS SDK は、次のような重要なサービスをアプリケーションに提供します。
+ HTTP (S) リクエストのフォーマットと、リクエストパラメータのシリアル化。
+ リクエストごとの暗号化署名の生成。
+ DynamoDB エンドポイントへのリクエストの転送と、DynamoDB からのレスポンスの受信。
+ これらの応答からの結果の抽出。
+ エラーが発生した場合の基本的な再試行ロジックの実装。

これらのタスクでは、コードを記述する必要はありません。

**注記**  
AWS SDK のインストール方法とドキュメントの詳細については、「[アマゾン ウェブ サービス用ツール](https://aws.amazon.com/tools)」を参照してください。

## AWS アカウントベースのエンドポイントの SDK サポート
<a name="Programming.SDKs.endpoints"></a>

AWS は、2024 年 9 月 4 日、SDK for Java V1 から、DynamoDB の AWS アカウントベースのエンドポイントの AWS SDK サポートをロールアウトします。これらの新しいエンドポイントは、高いパフォーマンスとスケーラビリティを AWS で確保するのに役立ちます。更新された SDK では、`https://(account-id).ddb.(region).amazonaws.com` 形式の新しいエンドポイントを自動的に使用します。

SDK クライアントの 1 つのインスタンスを使用して複数のアカウントにリクエストを行う場合、アプリケーションは接続を再利用する機会が少なくなります。AWS では、SDK クライアントインスタンスあたりの接続先のアカウント数を減らすようにアプリケーションを変更することをお勧めします。代わりに、「[AWS SDK およびツールリファレンスガイド](https://docs.aws.amazon.com/sdkref/latest/guide/feature-account-endpoints.html)」に記載されているように、`ACCOUNT_ID_ENDPOINT_MODE` 設定を使用してリージョンエンドポイントを引き続き使用するように SDK クライアントを設定することもできます。**

# DynamoDB で動作するプログラムインターフェイス
<a name="Programming.SDKs.Interfaces"></a>

各 [AWS SDK](https://aws.amazon.com/tools) には、Amazon DynamoDB を操作するプログラミングインターフェイスが 1 つ以上用意されています。これらのインターフェイスは、シンプルな低レベルの DynamoDB ラッパーから、オブジェクト指向の永続レイヤーまで、多岐にわたります。使用可能なインターフェイスは、AWS SDK およびプログラミング言語によって異なります。

![\[DynamoDB を使用するためのさまざまな AWS SDK で利用可能なプログラミングインターフェイス。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/SDKSupport.SDKInterfaces.png)


次のセクションでは、AWS SDK for Java を例として使用して、使用可能なインターフェイスをいくつかハイライトします。(すべてのインターフェイスが、どの AWS SDK でも使用できるわけではありません。)

**Topics**
+ [

## DynamoDB で動作する低レベルインターフェイス
](#Programming.SDKs.Interfaces.LowLevel)
+ [

## DynamoDB で動作するドキュメントインターフェイス
](#Programming.SDKs.Interfaces.Document)
+ [

## DynamoDB で動作するオブジェクト永続性インターフェイス
](#Programming.SDKs.Interfaces.Mapper)

## DynamoDB で動作する低レベルインターフェイス
<a name="Programming.SDKs.Interfaces.LowLevel"></a>

それぞれの言語特有の AWS SDK は、低レベルの DynamoDB API リクエストによく似たメソッドを持つ、Amazon DynamoDB 用の低レベルインターフェイスを提供します。

場合によっては [データ型記述子](Programming.LowLevelAPI.md#Programming.LowLevelAPI.DataTypeDescriptors) を使用して、文字列型の `S` や、数値型の `N` など、属性のデータ型を識別する必要があります。

**注記**  
すべての言語特有の AWS SDK で、低レベルインターフェイスを使用できます。

次の Java プログラムは、AWS SDK for Java の低レベルインターフェイスを使用しています。

### 低レベルインターフェイスの例
<a name="low-level-example"></a>

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 *
 * To get an item from an Amazon DynamoDB table using the AWS SDK for Java V2,
 * its better practice to use the
 * Enhanced Client, see the EnhancedGetItem example.
 */
public class GetItem {
    public static void main(String[] args) {
        final String usage = """

                Usage:
                    <tableName> <key> <keyVal>

                Where:
                    tableName - The Amazon DynamoDB table from which an item is retrieved (for example, Music3).\s
                    key - The key used in the Amazon DynamoDB table (for example, Artist).\s
                    keyval - The key value that represents the item to get (for example, Famous Band).
                """;

        if (args.length != 3) {
            System.out.println(usage);
            System.exit(1);
        }

        String tableName = args[0];
        String key = args[1];
        String keyVal = args[2];
        System.out.format("Retrieving item \"%s\" from \"%s\"\n", keyVal, tableName);
        Region region = Region.US_EAST_1;
        DynamoDbClient ddb = DynamoDbClient.builder()
                .region(region)
                .build();

        getDynamoDBItem(ddb, tableName, key, keyVal);
        ddb.close();
    }

    public static void getDynamoDBItem(DynamoDbClient ddb, String tableName, String key, String keyVal) {
        HashMap<String, AttributeValue> keyToGet = new HashMap<>();
        keyToGet.put(key, AttributeValue.builder()
                .s(keyVal)
                .build());

        GetItemRequest request = GetItemRequest.builder()
                .key(keyToGet)
                .tableName(tableName)
                .build();

        try {
            // If there is no matching item, GetItem does not return any data.
            Map<String, AttributeValue> returnedItem = ddb.getItem(request).item();
            if (returnedItem.isEmpty())
                System.out.format("No item found with the key %s!\n", key);
            else {
                Set<String> keys = returnedItem.keySet();
                System.out.println("Amazon DynamoDB table attributes: \n");
                for (String key1 : keys) {
                    System.out.format("%s: %s\n", key1, returnedItem.get(key1).toString());
                }
            }

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
}
```

## DynamoDB で動作するドキュメントインターフェイス
<a name="Programming.SDKs.Interfaces.Document"></a>

多くの AWS SDK はドキュメントインターフェイスを備えており、テーブルやインデックスに対してデータプレーンオペレーション (作成、読み取り、更新、削除) を実行できます。ドキュメントインターフェイスでは、[データ型記述子](Programming.LowLevelAPI.md#Programming.LowLevelAPI.DataTypeDescriptors) を指定する必要はありません。データ型は、データ自体のセマンティクスによって暗示されています。これらの AWS SDK には、JSON ドキュメントとネイティブの Amazon DynamoDB データ型とを簡単に変換するメソッドも用意されています。

**注記**  
ドキュメントインターフェイスは、AWS SDK for [Java](https://aws.amazon.com/sdk-for-java)、[.NET](https://aws.amazon.com/sdk-for-net)、[Node.js](https://aws.amazon.com/sdk-for-node-js)、および [JavaScript SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/) で使用できます。

次の Java プログラムは、AWS SDK for Java のドキュメントインターフェイスを使用します。プログラムが `Music` テーブルを表す `Table` オブジェクトを作成し、そのオブジェクトに `GetItem` の使用を依頼して、曲を取得します。その後プログラムが、曲がリリースされた年を出力します。

`software.amazon.dynamodb.document.DynamoDB` クラスは DynamoDB ドキュメントインターフェイスを実装します。低レベルクライアント (`AmazonDynamoDB`) のラッパーとして、`DynamoDB` がどのような役割を果たすかに注目してください。

### ドキュメントインターフェイスの例
<a name="document-level-example"></a>

```
package com.amazonaws.codesamples.gsg;

import software.amazon.dynamodb.AmazonDynamoDB;
import software.amazon.dynamodb.AmazonDynamoDBClientBuilder;
import software.amazon.dynamodb.document.DynamoDB;
import software.amazon.dynamodb.document.GetItemOutcome;
import software.amazon.dynamodb.document.Table;

public class MusicDocumentDemo {

    public static void main(String[] args) {

        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
        DynamoDB docClient = new DynamoDB(client);

        Table table = docClient.getTable("Music");
        GetItemOutcome outcome = table.getItemOutcome(
                "Artist", "No One You Know",
                "SongTitle", "Call Me Today");

        int year = outcome.getItem().getInt("Year");
        System.out.println("The song was released in " + year);

    }
}
```

## DynamoDB で動作するオブジェクト永続性インターフェイス
<a name="Programming.SDKs.Interfaces.Mapper"></a>

一部の AWS SDK には、データプレーンオペレーションを直接実行しない、オブジェクト永続性インターフェイスが用意されています。代わりに、Amazon DynamoDB のテーブルとインデックスの項目を表すオブジェクトを作成し、それらのオブジェクトのみとやり取りを行います。これにより、データベースを意識するのではなく、オブジェクトを中心にコードを作成していくことができます。

**注記**  
オブジェクト永続性インターフェイスは、AWS SDK for Java と for .NET で利用できます。詳細については、DynamoDB の「[DynamoDB の上位レベルのプログラミングインターフェイス](HigherLevelInterfaces.md)」を参照してください。

### オブジェクト永続性インターフェイスの例
<a name="mapper-level-example"></a>

```
import com.example.dynamodb.Customer;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedRequest;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
```

```
import com.example.dynamodb.Customer;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedRequest;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;

/*
 * Before running this code example, create an Amazon DynamoDB table named Customer with these columns:
 *   - id - the id of the record that is the key. Be sure one of the id values is `id101`
 *   - custName - the customer name
 *   - email - the email value
 *   - registrationDate - an instant value when the item was added to the table. These values
 *                        need to be in the form of `YYYY-MM-DDTHH:mm:ssZ`, such as 2022-07-11T00:00:00Z
 *
 * Also, ensure that you have set up your development environment, including your credentials.
 *
 * For information, see this documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */

public class EnhancedGetItem {
    public static void main(String[] args) {
        Region region = Region.US_EAST_1;
        DynamoDbClient ddb = DynamoDbClient.builder()
                .region(region)
                .build();

        DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();

        getItem(enhancedClient);
        ddb.close();
    }

    public static String getItem(DynamoDbEnhancedClient enhancedClient) {
        Customer result = null;
        try {
            DynamoDbTable<Customer> table = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
            Key key = Key.builder()
                    .partitionValue("id101").sortValue("tred@noserver.com")
                    .build();

            // Get the item by using the key.
            result = table.getItem(
                    (GetItemEnhancedRequest.Builder requestBuilder) -> requestBuilder.key(key));
            System.out.println("******* The description value is " + result.getCustName());

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        return result.getCustName();
    }
}
```

# DynamoDB の上位レベルのプログラミングインターフェイス
<a name="HigherLevelInterfaces"></a>

AWS SDK は、Amazon DynamoDB を操作するための下位レベルのインターフェイスをアプリケーションに提供します。これらのクライアント側のクラスとメソッドは、下位レベルの DynamoDB API と直接対応しています。しかし、これは多くのデベロッパーにとって、複雑なデータ型をデータベーステーブル内の項目にマップする必要がある場合の接続性の悪さ、つまり*インピーダンスの不整合*の原因となります。下位レベルのデータベースインタフェースを使用するデベロッパーは、オブジェクトデータをデータベーステーブルに対して読み書きするためのメソッドを記述する必要があります。オブジェクトタイプとデータベーステーブルの組み合わせに、個別に対応するための余分なコードが、圧倒的な量になることもあります。

AWS SDK for Java および for .NET では、開発業務を簡素化するために、高度に抽象化されたインターフェイスが用意されています。DynamoDB の上位レベルのインターフェイスを使用すると、プログラム内のオブジェクトと、それらのオブジェクトのデータを格納するためのデータベーステーブル間の関係を定義できます。このマッピングを定義した後、`save`、`load`、`delete` などの単純なオブジェクトメソッドを呼び出すと、ユーザーに代わって、基盤となる下位レベルの DynamoDB オペレーションの呼び出しが自動化されます。これにより、データベースを意識するのではなく、オブジェクトを中心にコードを作成していくことができます。

DynamoDB の上位レベルのプログラミングインターフェイスは、Java および .NET 用の AWS SDK で使用できます。

**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>

**注記**  
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)」を参照してください。**

# Java 2.x: DynamoDB 拡張クライアント
<a name="DynamoDBEnhanced"></a>

DynamoDB 拡張クライアントは、AWS SDK for Java バージョン 2 (v2) の一部である高レベルのライブラリです。クライアント側のクラスを DynamoDB テーブルにマッピングする簡単な方法を提供します。テーブルおよび対応するモデルクラスの間の関係をコードで定義します。関係を定義したら、DynamoDB のテーブルまたは項目に対して、さまざまな作成、読み取り、更新、または削除 (CRUD) オペレーションを直感的に実行できます。

DynamoDB で拡張クライアントを使用する方法の詳細については、「[AWS SDK for Java 2.x での DynamoDB 拡張クライアントの使用](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)」を参照してください。

# DynamoDB での .NET ドキュメントの操作
<a name="DotNetSDKMidLevel"></a>

AWS SDK for .NET では、低レベル 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`（バイナリ型）   | 
| ブール | N (数値型)。0 は false、1 は true を表します。 | 
| DateTime | S (文字列型)。DateTime の値は、ISO-8601 形式の文字列として格納されます。 | 
| Guid | S (文字列型)。 | 
| コレクション型 (リスト、ハッシュセット、配列) | BS（バイナリセット）型、SS（文字列セット）型、NS（数値セット）型 | 

AWS SDK for .NET は、DynamoDB のブール型、null 型、リスト型、およびマップ型を .NET ドキュメントモデル API にマッピングするための型を定義します。
+ ブール型には `DynamoDBBool` 使用します。
+ null 型には `DynamoDBNull` を使用します。
+ リスト型には `DynamoDBList` を使用します。
+ マップ型には `Document` を使用します。

**注記**  
空のバイナリ値がサポートされています。
空の文字列値の読み取りがサポートされています。空の文字列属性値は、DynamoDB への書き込み中に、文字列セット型の属性値内でサポートされます。文字列型の空の文字列属性値と、リスト型またはマップ型に含まれる空の文字列値が書き込みリクエストから削除されます。

# .NET オブジェクト永続性モデルと DynamoDB の使用
<a name="DotNetSDKHighLevel"></a>

AWS SDK for .NET には、クライアント側クラスを Amazon DynamoDB テーブルにマッピングできるオブジェクト永続性モデルを有効にしています。各オブジェクトインスタンスが、対応するテーブルの項目にマッピングされます。クライアント側オブジェクトをテーブルに保存するために、オブジェクト永続性モデルでは、DynamoDB のエントリポイントとして `DynamoDBContext` クラスを使用できます。このクラスでは、DynamoDB に接続してテーブルにアクセスし、各種の CRUD オペレーションやクエリを実行することができます。

オブジェクト永続性モデルには、クライアント側クラスをテーブルにマッピングし、プロパティ/フィールドを属性にマッピングする、属性のセットが用意されています。

**注記**  
オブジェクト永続性モデルには、テーブルを作成、更新、または削除するための API はありません。データオペレーションだけが可能になっています。テーブルの作成、更新、削除が可能なのは AWS SDK for .NET の低レベル API だけです。

次の例は、オブジェクト永続性モデルの動作を示しています。`ProductCatalog` テーブルから開始します。ここでは `Id` がプライマリキーになっています。

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

`Book`、`Title`、`ISBN` プロパティを持つ `Authors` クラスがあるとします。次の C\$1 サンプルコードに示すように、オブジェクト永続性モデルで定義された属性を追加することで、`Book` クラスを `ProductCatalog` テーブルにマッピングできます。

**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` プロパティが `Authors` テーブル内の `ProductCatalog` 属性にマッピングされています。
+ **デフォルトのマッピング** – デフォルトでは、オブジェクト永続性モデルによって、クラスプロパティがテーブル内の同じ名前の属性にマッピングされます。

  前述の例では、`Title` および `ISBN` プロパティが、`ProductCatalog` テーブル内の同じ名前の属性にマッピングされています。

すべてのクラスプロパティをマッピングする必要はありません。これらのプロパティを特定するには、`DynamoDBIgnore` 属性を追加します。`Book` インスタンスをテーブルに保存する場合、`DynamoDBContext` には `CoverPage` プロパティは含まれません。このプロパティは、書籍インスタンスを取り出す場合にも返されません。

int や string など、.NET プリミティブ型のプロパティをマッピングできます。また、任意データをいずれかの DynamoDB 型にマッピングする適切なコンバーターがある限り、任意のデータ型をマッピングすることもできます。任意の型のマッピングについては、「[AWS SDK for .NET のオブジェクト永続性モデルを使用した、DynamoDB での任意データのマッピング](DynamoDBContext.ArbitraryDataMapping.md)」を参照してください。

オブジェクト永続性モデルでは、オプティミスティックロックがサポートされています。それによって、更新オペレーションで、更新する項目の最新のコピーを確実に使用することができます。詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](DynamoDBContext.VersionSupport.md)」を参照してください。

詳細については、以下のトピックを参照してください。

**Topics**
+ [

## サポートされているデータ型
](#DotNetDynamoDBContext.SupportedTypes)
+ [

# .NET オブジェクト永続性モデルからの DynamoDB 属性
](DeclarativeTagsList.md)
+ [

# .NET オブジェクト永続性モデルからの DynamoDBContext クラス
](DotNetDynamoDBContext.md)
+ [

# DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック
](DynamoDBContext.VersionSupport.md)
+ [

# AWS SDK for .NET のオブジェクト永続性モデルを使用した、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` は具体的なコレクション型、およびシンプルな Plain Old CLR Objects (POCOs) を変換できます。

次の表に、前述の .NET 型が DynamoDB の型にどのようにマッピングされるかを示します。


****  

| .NET プリミティブ型 | DynamoDB 型 | 
| --- | --- | 
|  すべての数値型  |  `N`（数値型）  | 
|  すべての文字列型  |  `S` (文字列型)   | 
|  MemoryStream、byte[]  |  `B`（バイナリ型）   | 
| ブール | N (数値型)。0 は false、1 は true を表します。 | 
| コレクション型 | BS（バイナリセット）型、SS（文字列セット）型、NS（数値セット）型 | 
| DateTime | S (文字列型)。DateTime の値は、ISO-8601 形式の文字列として格納されます。 | 

オブジェクト永続性モデルでは、任意のデータ型もサポートされています。ただし、複合型を DynamoDB 型にマッピングする場合には、変換用のコードを用意する必要があります。

**注記**  
空のバイナリ値がサポートされています。
空の文字列値の読み取りがサポートされています。空の文字列属性値は、DynamoDB への書き込み中に、文字列セット型の属性値内でサポートされます。文字列型の空の文字列属性値と、リスト型またはマップ型に含まれる空の文字列値が書き込みリクエストから削除されます。

# .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` テーブルにマッピングします。クラス定義では、プロパティのうち 2 つがプライマリキーにマッピングされることも示しています。

```
[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` 属性は継承できます。前述の例では、`Lead` クラスから継承された新しいクラス `Developer` を追加すると、`People` テーブルにもマッピングされます。`Developer` テーブルに `Lead` と `People` の両方のオブジェクトが格納されます。
+ `DynamoDBTable` 属性もオーバーライドできます。次の C\$1 サンプルコードでは、`Manager` クラスは、`Developer` クラスから継承されます。ただし、`DynamoDBTable` 属性を明示的に追加すると、クラスは別のテーブル (`Managers`) にマップされます。

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

 次の C\$1 の例に示すように、オプションのパラメータ `LowerCamelCaseProperties` を追加すると、オブジェクトをテーブルに格納する際にプロパティ名の先頭文字を小文字にするよう、DynamoDB にリクエストを送ることができます。

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

`Developer` クラスのインスタンスを保存する場合、`DynamoDBContext` では `DeveloperName` プロパティが `developerName` として保存されます。

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

項目のバージョン番号を格納するクラスプロパティを識別します。バージョニングの詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](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)
+ [

## Delete
](#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)
+ [

## 保存
](#w2aac17b9c21c23c39c35)
+ [

## Scan
](#w2aac17b9c21c23c39c37)
+ [

## ToDocument
](#w2aac17b9c21c23c39c39)
+ [

## DynamoDBContext でのオプションパラメータの指定
](#OptionalConfigParams)

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

複数の個々の `MultiTableBatchGet` オブジェクトで構成される `BatchGet` オブジェクトを作成します。これらの各 `BatchGet` オブジェクトは、単一の DynamoDB テーブルから項目を取り出す場合に使用します。

1 つ以上のテーブルから項目を取得するには、`ExecuteBatchGet` メソッドを使用し、`MultiTableBatchGet` オブジェクトをパラメータとして渡します。

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

複数の個々の `MultiTableBatchWrite` オブジェクトで構成される `BatchWrite` オブジェクトを作成します。これらの各 `BatchWrite` オブジェクトは、単一の DynamoDB テーブルに項目を書き込んだり、それを削除したりするために使用します。

テーブルに書き込むには、`ExecuteBatchWrite` メソッドを使用し、`MultiTableBatchWrite` オブジェクトをパラメータとして渡します。

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

テーブルから複数の項目を取り出すために使用できる `BatchGet` オブジェクトを作成します。

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

テーブルに複数の項目を入力する、またはテーブルから複数の項目を削除するために使用できる `BatchWrite` オブジェクトを作成します。

## Delete
<a name="w2aac17b9c21c23c39c15"></a>

テーブルから項目を削除します。このメソッドでは、削除する項目のプライマリキーが必要になります。プライマリキーの値、またはこのメソッドのパラメータとしてプライマリキーの値を使用するクライアント側オブジェクトを入力できます。
+ クライアント側オブジェクトをパラメータとして指定し、オプティミスティックロックを有効にすると、クライアント側とサーバー側のオブジェクトのバージョンが一致する場合のみ、削除が成功します。
+ プライマリキーの値だけをパラメータとして指定すると、オプティミスティックロックを有効にしているかどうかにかかわらず、削除が成功します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`DeleteAsync` メソッドを使用します。

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

すべてのマネージドリソースとアンマネージドリソースを破棄します。

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

1 つ以上のテーブルからデータを読み込みます。`BatchGet` 内のすべての `MultiTableBatchGet` オブジェクトを処理します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`ExecuteBatchGetAsync` メソッドを使用します。

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

1 つ以上のテーブルにデータを書き込むまたは削除します。`BatchWrite` 内のすべての `MultiTableBatchWrite` オブジェクトを処理します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`ExecuteBatchWriteAsync` メソッドを使用します。

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

`Document` のインスタンスと仮定すると、`FromDocument` メソッドは、クライアント側のクラスのインスタンスを返します。

これは、オブジェクト永続性モデルと合わせてドキュメントモデルクラスを使用してデータオペレーションを行う場合に役立ちます。AWS SDK for .NET で使用されるドキュメントモデルクラスの詳細については、「[DynamoDB での .NET ドキュメントの操作](DotNetSDKMidLevel.md)」を参照してください。

`Document` という名前の `doc` オブジェクトがあり、`Forum` 項目の表現を含んでいるとします。(このオブジェクトの構成方法については、下の `ToDocument` メソッドの説明を参照してください)。次の C\$1 サンプルコードに示すように、`FromDocument` を使用して `Forum` から `Document` 項目を取得することができます。

**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` コレクションが返ります。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一致する項目をすべて取得するには、`IEnumerable` を反復的に処理します。

テーブルにシンプルなプライマリキー (パーティションキー) がある場合は、`Query` メソッドを使用できません。代わりに `Load` メソッドを使用して、パーティションキーを入力して項目を取り出すことができます。

**注記**  
このオペレーションをバックグラウンドで実行するには、`QueryAsync` メソッドを使用します。

## 保存
<a name="w2aac17b9c21c23c39c35"></a>

指定したオブジェクトがテーブルに保存されます。入力オブジェクトで指定されたプライマリキーがテーブル内に存在しない場合は、このメソッドによって新しい項目がテーブルに追加されます。プライマリキーが存在する場合は、このメソッドによって既存の項目が更新されます。

オプティミスティックロックを設定している場合には、クライアント側とサーバー側で項目のバージョンが一致する場合のみ、更新が正常に実行されます。詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](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` コレクションが返ります。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一致するすべての項目は、`IEnumerable` を反復的に処理するだけで取得できます。

パフォーマンス上の理由から、テーブルについてはスキャンを避け、クエリを行うようにしてください。

**注記**  
このオペレーションをバックグラウンドで実行するには、`ScanAsync` メソッドを使用します。

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

クラスインスタンスから、`Document` ドキュメントモデルクラスのインスタンスが返されます。

これは、オブジェクト永続性モデルと合わせてドキュメントモデルクラスを使用してデータオペレーションを行う場合に役立ちます。AWS SDK for .NET で使用されるドキュメントモデルクラスの詳細については、「[DynamoDB での .NET ドキュメントの操作](DotNetSDKMidLevel.md)」を参照してください。

クライアント側のクラスが `Forum` サンプルテーブルにマッピングされているとします。その場合は次の C\$1 サンプルコードに示すように、`DynamoDBContext` を使用して、`Document` テーブルから項目を `Forum` オブジェクトとして取得することができます。

**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`-**このパラメータにより、`Save` オペレーション時に属性の null 値を無視するように `DynamoDBContext` に指示できます。このパラメータが false の場合 (または設定されていない場合)、null 値は、特定の属性を削除するディレクティブと見なされます。
+ **`SkipVersionCheck`–**このパラメータは、項目の保存または削除を実行する際、バージョンの比較を行わないように `DynamoDBContext` に指示します。バージョニングの詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](DynamoDBContext.VersionSupport.md)」を参照してください。
+ **`TableNamePrefix`-**すべてのテーブル名に特定の文字列をプレフィックスします。このパラメータが null の場合（または設定されていない場合）、プレフィックスは使用されません。
+ `DynamoDBEntryConversion` – クライアントで使用する変換スキーマを指定します。このパラメータはバージョン V1 または V2 に設定できます。デフォルトのバージョンは V1 です。

  設定したバージョンに応じて、このパラメータの動作が変わります。例えば、次のようになります。
  + V1 では、`bool` データ型が `N` 数値型に変換されます。0 は false、1 は true を表します。V2 では、`bool` が `BOOL` に変換されます。
  + V2 の場合、リストと配列は HashSets と一緒にグループ化されません。数値、文字列ベースの型、バイナリベースの型のリストと配列は `L` (List) 型に変換され、リストを更新するために空で送信できます。この動作は、空のリストがワイヤ経由で送信されない V1 とは異なります。

    V1 の場合、List、HashSet、配列などのコレクションタイプは同じように扱われます。List、HashSet、数値の配列は `NS` (数値セット) 型に変換されます。

  次の例では、変換スキーマのバージョンを V2 に設定し、.NET 型と DynamoDB データ型間の変換動作を変更します。

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

次の C\$1 サンプルコードでは、前述のオプションパラメータのうち 2 つ (`ConsistentRead` と `SkipVersionCheck`) を指定して、新しい `DynamoDBContext` を作成します。

**Example**  

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

`DynamoDBContext` では、このコンテキストを使用して送信した各リクエストに、これらのオプションパラメータが含められます。

次の C\$1 サンプルコードに示すように、これらのパラメータを `DynamoDBContext` レベルで設定する代わりに、`DynamoDBContext` を使用して実行するオペレーションに対して個別に指定することもできます。この例では特定の書籍項目がロードされています。`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 と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック
<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 を割り当てます。既存の項目を取得し、1 つ以上のプロパティを更新して変更を保存しようとすると、保存オペレーションは、クライアント側とサーバー側のバージョン番号が一致する場合にのみ成功します。`DynamoDBContext` によってバージョン番号が増加します。バージョン番号を設定する必要はありません。
+ 次の C\$1 サンプルコードに示すように、`Delete` メソッドでは、プライマリキーの値またはオブジェクトのいずれかをパラメータとして指定できるオーバーロードを使用できます。  
**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 });
```

# AWS SDK for .NET のオブジェクト永続性モデルを使用した、DynamoDB での任意データのマッピング
<a name="DynamoDBContext.ArbitraryDataMapping"></a>

サポート済みの .NET 型 (「[サポートされているデータ型](DotNetSDKHighLevel.md#DotNetDynamoDBContext.SupportedTypes)」を参照) に加えて、アプリケーション内にあり Amazon DynamoDB 型に直接マッピングされていない型を使用できます。オブジェクト永続性モデルでは、任意型から DynamoDB 型に (またはその反対に) データを変換できるコンバーターを用意することで、任意型のデータを格納できます。コンバーターコードによって、オブジェクトの保存およびロード中にデータが変換されます。

クライアント側で任意の型を作成できます。ただし、テーブルには、いずれかの DynamoDB 型を使用してデータが格納されます。また、クエリおよびスキャンの際のデータ比較は、DynamoDB に格納されているデータに対して行われます。

次の C\$1 コード例では、`Book`、`Id`、`Title`、および `ISBN` プロパティを使用して `Dimension` クラスを定義しています。`Dimension` プロパティは、`DimensionType`、`Height`、および `Width` プロパティを記述する `Thickness` に含まれています。このコード例では、コンバーターメソッド `ToEntry` および `FromEntry` によって、`DimensionType` と DynamoDB の文字列型との間でデータが変換されます。たとえば、`Book` インスタンスを保存すると、コンバータによって、「8.5 x 11 x 05」などの書籍 `Dimension` 文字列が作成されます。書籍を取得すると、その文字列は `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;
        }
    }
}
```

# このデベロッパーガイドのコード例の実行
<a name="CodeSamples"></a>

AWS SDK では、次の言語で Amazon DynamoDB を幅広くサポートしています。
+ [Java](https://aws.amazon.com/sdk-for-java): 
+ [ブラウザの JavaScript](https://aws.amazon.com/sdk-for-browser)
+ [.NET](https://aws.amazon.com/sdk-for-net)
+ [Node.js](https://aws.amazon.com/sdk-for-node-js)
+ [PHP](https://aws.amazon.com/sdk-for-php)
+ [Python](https://aws.amazon.com/sdk-for-python) \$1
+ [Ruby](https://aws.amazon.com/sdk-for-ruby)
+ [C\$1\$1](https://aws.amazon.com/sdk-for-cpp)
+ [Go](https://aws.amazon.com/sdk-for-go): 
+ [Android](https://aws.amazon.com/mobile/sdk/)
+ [iOS](https://aws.amazon.com/mobile/sdk/)

この開発者ガイドのコード例は、以下のプログラミング言語を使用して DynamoDB オペレーションの詳細を示しています。
+ [Java コードの例](CodeSamples.Java.md)
+ [.NET コード例](CodeSamples.DotNet.md)

この演習を開始する前に、AWS アカウントを作成し、アクセスキーとシークレットキーを取得して、コンピュータで AWS Command Line Interface (AWS CLI) をセットアップします。詳細については、「」を参照してください[DynamoDB (ウェブサービス) の設定](SettingUp.DynamoWebService.md)

**注記**  
DynamoDB のダウンロード可能バージョンを使用する場合は、AWS CLI を使用してテーブルとサンプルデータを作成する必要があります。また、各 `--endpoint-url` コマンドで AWS CLI パラメータも指定する必要があります。詳細については、「[ローカルエンドポイントの設定](DynamoDBLocal.UsageNotes.md#DynamoDBLocal.Endpoint)」を参照してください。

# DynamoDB でのコード例用のテーブルの作成とデータのロード
<a name="SampleData"></a>

DynamoDB でのテーブルの作成、サンプルデータセットのロード、データに対するクエリの実行、およびデータの更新に関する基本については、以下を参照してください。
+ [ステップ 1: DynamoDB にテーブルを作成する](getting-started-step-1.md)
+ [ステップ 2: DynamoDB テーブルにデータを書き込む](getting-started-step-2.md)
+ [ステップ 3: DynamoDB テーブルからデータを読み込む](getting-started-step-3.md)
+ [ステップ 4: DynamoDB テーブルのデータを更新する](getting-started-step-4.md)

# Java コードの例
<a name="CodeSamples.Java"></a>

**Topics**
+ [

## Java: AWS 認証情報の設定
](#CodeSamples.Java.Credentials)
+ [

## Java: AWS リージョンとエンドポイントの設定
](#CodeSamples.Java.RegionAndEndpoint)

この開発者ガイドには、Java コードスニペットとすぐに使用できるプログラムが含まれています。これらのコード例は、次のセクションで確認することができます。
+ [DynamoDB での項目と属性の操作](WorkingWithItems.md)
+ [DynamoDB でのテーブルとデータの操作](WorkingWithTables.md)
+ [DynamoDB のテーブルに対するクエリの実行](Query.md)
+ [DynamoDB でのテーブルのスキャン](Scan.md)
+ [DynamoDB でのセカンダリインデックスを使用したデータアクセス性の向上](SecondaryIndexes.md)
+ [Java 1.x: DynamoDBMapper](DynamoDBMapper.md)
+ [DynamoDB Streams の変更データキャプチャ](Streams.md)

Eclipse と [AWS Toolkit for Eclipse](https://aws.amazon.com/eclipse/) を使用して、すぐに開始できます。フル機能の IDE に加えて、自動更新で AWS SDK for Java および AWS アプリケーションの構築用に事前設定されたテンプレートも取得できます。

**Java サンプルコードを実行するには (Eclipse を使用)**

1. [Eclipse](http://www.eclipse.org) IDE をダウンロードし、インストールします。

1. のダウンロードおよびインストール。[AWS Toolkit for Eclipse](https://aws.amazon.com/eclipse/)。

1. Eclipse を起動し、**Eclipse** メニューから、**[File]** (ファイル)、**[New]** (新規)、**[Other]** (その他) の順に選択します。

1. **[Select a wizard]** (ウィザードの選択) で、**AWS**、**[AWS Java Project]** ( Java プロジェクト) の順に選択してから、**[Next]** (次へ) をクリックします。

1. **[AWS Java の作成]** で、次の操作を行います。

   1. **[Project name]** (プロジェクト名) にプロジェクトの名前を入力します。

   1. **[Select Account]** (アカウントの選択) リストから認証情報プロファイルを選択します。

      [AWS Toolkit for Eclipse](https://aws.amazon.com/eclipse/) を初めて使用する場合、**[AWS アカウントの設定]** を選択して、AWS 認証情報を設定します。

1. **[Finish]** (完了) を選択してプロジェクトを作成します。

1. **Eclipse** メニューから **[File]** (ファイル)、**[New]** (新規)、**[Class]** (クラス) の順に選択します。

1. **[Java Class]** (Java クラス) の **[Name]** (名前) にクラスの名前を入力し (実行するコード例と同じ名前を使用)、**[Finish]** (完了) を選択してクラスを作成します。

1. ドキュメントページから Eclipse エディタにサンプルコードをコピーします。

1. コードを実行するには、Eclipse メニューの **[Run]** (実行) を選択します。

SDK for Java には、DynamoDB を操作するためにスレッドセーフなクライアントが用意されています。ベストプラクティスとして、ご利用のアプリケーションでクライアントを 1 つ作成し、そのクライアントをスレッド間で再利用します。

詳細については、[AWS SDK for Java](https://aws.amazon.com/sdk-for-java) を参照してください。

**注記**  
このガイドのサンプルコードは、最新バージョンの AWS SDK for Java で使用するためのものです。  
AWS Toolkit for Eclipse を使用している場合、SDK for Java の自動更新を設定することができます。これを Eclipse で行うには、**[Preferences]** (基本設定) に移動し、**AWS Toolkit**、**AWS SDK for Java**、**[Download new SDKs automatically]** (新しい SDK を自動的にダウンロード) の順に選択します。

## Java: AWS 認証情報の設定
<a name="CodeSamples.Java.Credentials"></a>

SDK for Java では、ランタイムにアプリケーションに AWS 認証情報を指定する必要があります。このガイドのコード例では、AWS 認証情報ファイルを使用していることを前提としています。詳細については、「AWS SDK for Java デベロッパーガイド」の「[開発用の AWS 認証情報のセットアップ](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/set-up-creds.html)」を参照してください。

`~/.aws/credentials` という名前の AWS 認証情報ファイルの例を次に示します。ここで、チルダ文字 (`~`) はホームディレクトリを表します。

```
[default]
aws_access_key_id = AWS access key ID goes here
aws_secret_access_key = Secret key goes here
```

## Java: AWS リージョンとエンドポイントの設定
<a name="CodeSamples.Java.RegionAndEndpoint"></a>

デフォルトでは、コード例は、米国西部 (オレゴン) リージョンの DynamoDB にアクセスします。このリージョンを変更するには、`AmazonDynamoDB` プロパティを変更します。

次のサンプルコードは、新しい `AmazonDynamoDB` をインスタンス化します。

```
import software.amazon.dynamodb.AmazonDynamoDBClientBuilder;
import com.amazonaws.regions.Regions;
...
// This client will default to US West (Oregon)
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(Regions.US_WEST_2)
.build();
```

`withRegion` メソッドを使用して、利用可能な任意のリージョンで、DynamoDB を対象としてコードを実行できます。リージョンのリストについては、「*Amazon Web Services 全般のリファレンス*」の「[AWS リージョンとエンドポイント](https://docs.aws.amazon.com/general/latest/gr/rande.html#ddb_region)」を参照してください。

ローカルコンピュータで DynamoDB を使用してサンプルコードを実行する場合は、エンドポイントを設定する必要があります。

### AWS SDKV1
<a name="CodeSamples.Java.RegionAndEndpoint.V1"></a>

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(
new AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();
```

### AWS SDK V2
<a name="CodeSamples.Java.RegionAndEndpoint.V2"></a>

```
DynamoDbClient client = DynamoDbClient.builder()
    .endpointOverride(URI.create("http://localhost:8000"))
    // The region is meaningless for local DynamoDb but required for client builder validation
    .region(Region.US_EAST_1)
    .credentialsProvider(StaticCredentialsProvider.create(
    AwsBasicCredentials.create("dummy-key", "dummy-secret")))
    .build();
```

# .NET コード例
<a name="CodeSamples.DotNet"></a>

**Topics**
+ [

## .NET: AWS 認証情報の設定
](#CodeSamples.DotNet.Credentials)
+ [

## .NET: AWS リージョンとエンドポイントの設定
](#CodeSamples.DotNet.RegionAndEndpoint)

このガイドには、.NET コードスニペットとすぐに使用できるプログラムが含まれています。これらのコード例は、次のセクションで確認することができます。
+ [DynamoDB での項目と属性の操作](WorkingWithItems.md)
+ [DynamoDB でのテーブルとデータの操作](WorkingWithTables.md)
+ [DynamoDB のテーブルに対するクエリの実行](Query.md)
+ [DynamoDB でのテーブルのスキャン](Scan.md)
+ [DynamoDB でのセカンダリインデックスを使用したデータアクセス性の向上](SecondaryIndexes.md)
+ [DynamoDB での .NET ドキュメントの操作](DotNetSDKMidLevel.md)
+ [.NET オブジェクト永続性モデルと DynamoDB の使用](DotNetSDKHighLevel.md)
+ [DynamoDB Streams の変更データキャプチャ](Streams.md)

AWS SDK for .NET と Toolkit for Visual Studio を使用すると、すぐに始めることができます。

**.NET サンプルコードを実行するには (Visual Studio を使用)**

1. [Microsoft Visual Studio](https://www.visualstudio.com) をダウンロードし、インストールします。

1. (オプション) [Toolkit for Visual Studio](https://aws.amazon.com/visualstudio/) をダウンロードしてインストールします。

1. AWS 認証情報をセットアップします。共有 AWS 認証情報ファイル (`~/.aws/credentials`) で認証情報プロファイルを設定します。詳細については、「*AWS SDK for .NET デベロッパーガイド*」の「[AWS 認証情報の設定](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-creds.html)」を参照してください。

1. Visual Studio を起動します。**[File]** (ファイル)、**[New]** (新規)、**[Project]** (プロジェクト) の順に選択します。

1. **[コンソールアプリ]** を検索し、.NET をターゲットとする C\$1 テンプレートを選択し、**[次へ]** を選択します。プロジェクト名と場所を設定し、**[作成]** を選択します。

1. プロジェクトに DynamoDB NuGet パッケージ用 AWS SDK を追加します。

   1. ソリューションエクスプローラーで、プロジェクトのコンテキスト (右クリック) メニューを開いて、**[Manage NuGet Packages]** (NuGet パッケージの管理) を選択します。

   1. NuGet パッケージマネージャーで、**[Browse]** (参照) を選択します。

   1. 検索ボックスに「**AWSSDK.DynamoDBv2**」と入力し、完了するまで待ちます。

   1. **AWSSDK.DynamoDBv2**、**[Install]** (インストール) の順に選択します。

1. Visual Studio プロジェクトで、`Program.cs` を開きます。内容を、実行するドキュメントページのコード例に置き換えます。

1. コードを実行するには、Visual Studio ツールバーの **[Start]** (開始) を選択します。

SDK for .NET には、DynamoDB を操作するためにスレッドセーフなクライアントが用意されています。ベストプラクティスとして、ご利用のアプリケーションでクライアントを 1 つ作成し、そのクライアントをスレッド間で再利用します。

詳細については、「[AWS SDK for .NET](https://aws.amazon.com/sdk-for-net)」を参照してください。

**注記**  
このガイドのサンプルコードは、最新バージョンの AWS SDK for .NET で使用するためのものです。

## .NET: AWS 認証情報の設定
<a name="CodeSamples.DotNet.Credentials"></a>

SDK for .NET では、ランタイムにアプリケーションに AWS 認証情報を指定する必要があります。このガイドのコード例は、SDK ストアを使用して AWS 認証情報ファイルを管理することを前提としています。詳細については、「*AWS SDK for .NET デベロッパーガイド*」の「[SDK ストアの使用](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-creds.html#sdk-store)」を参照してください。

Toolkit for Visual Studio では、任意の数のアカウントの複数セットの認証情報がサポートされています。各セットは*プロファイル*と呼ばれています。Visual Studio では、プロジェクトの `App.config` ファイルにエントリを追加するため、アプリケーションはランタイム時に AWS 認証情報を見つけることができます。

次の例は、Toolkit for Visual Studio を使用した新しいプロジェクトの作成時に生成されたデフォルトの `App.config` ファイルを示しています。

```
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
    <add key="AWSProfileName" value="default"/>
    <add key="AWSRegion" value="us-west-2" />
 </appSettings>
</configuration>
```

ランタイム時に、このプログラムは `AWSProfileName` エントリで指定されているように、AWS 認証情報の `default` セットを使用します。AWS 認証情報自体は、暗号化されたフォームで SDK ストアに保持されます。Toolkit for Visual Studio は、すべて Visual Studio 内からの認証情報を管理するためのグラフィカルユーザーインターフェイスを使用します。詳細については、「*AWS Toolkit for Visual Studio ユーザーガイド*」の「[認証情報の指定](https://docs.aws.amazon.com/AWSToolkitVS/latest/UserGuide/tkv_setup.html#creds)」を参照してください。

**注記**  
デフォルトでは、コード例は、米国西部 (オレゴン) リージョンの DynamoDB にアクセスします。リージョンを変更するには、App.config ファイルで `AWSRegion` エントリを変更します。`AWSRegion` を DynamoDB が利用可能なすべてのリージョンに設定します。リージョンのリストについては、「*Amazon Web Services 全般のリファレンス*」の「[AWS リージョンとエンドポイント](https://docs.aws.amazon.com/general/latest/gr/rande.html#ddb_region)」を参照してください。

## .NET: AWS リージョンとエンドポイントの設定
<a name="CodeSamples.DotNet.RegionAndEndpoint"></a>

デフォルトでは、コード例は、米国西部 (オレゴン) リージョンの DynamoDB にアクセスします。リージョンを変更するには、`AWSRegion` ファイルで `App.config` エントリを変更します。または、`AmazonDynamoDBClient` プロパティを変更してリージョンを変更することもできます。

次のサンプルコードは、新しい `AmazonDynamoDBClient` をインスタンス化します。クライアントは、別のリージョンでコードが DynamoDB に対して実行するように変更されます。

```
AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig();
// This client will access the US East 1 region.
clientConfig.RegionEndpoint = RegionEndpoint.USEast1;
AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig);
```

リージョンのリストについては、「*Amazon Web Services 全般のリファレンス*」の「[AWS リージョンとエンドポイント](https://docs.aws.amazon.com/general/latest/gr/rande.html#ddb_region)」を参照してください。

ローカルコンピュータで DynamoDB を使用してサンプルコードを実行する場合は、エンドポイントを設定する必要があります。

```
AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig();
// Set the endpoint URL
clientConfig.ServiceURL = "http://localhost:8000";
AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig);
```

# DynamoDB 低レベル API
<a name="Programming.LowLevelAPI"></a>

Amazon DynamoDB の*低レベル API* は、DynamoDB 用のプロトコルレベルのインターフェイスです。このレベルでは、すべての HTTP リクエストは、適切な形式で有効なデジタル署名がある必要があります。

AWS SDK は、低レベル DynamoDB API リクエストをユーザーに代わって作成し、DynamoDB からのレスポンスを処理します。これにより、低レベルの詳細ではなく、アプリケーションロジックに専念することができます。ただし、低レベル DynamoDB API の動作方法についての基本的な知識も役立ちます。

低レベル DynamoDB API の詳細については、[Amazon DynamoDB API リファレンス](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/)を参照してください。

**注記**  
DynamoDB Streams には、DynamoDB とは別に独自の低レベル API があり、AWS SDK で完全にサポートされています。  
詳細については、「[DynamoDB Streams の変更データキャプチャ](Streams.md)」を参照してください。低レベル DynamoDB Streams API については、[Amazon DynamoDB Streams API リファレンス](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations_Amazon_DynamoDB_Streams.html)を参照してください。

低レベル DynamoDB API は、ワイヤプロトコル形式として、JavaScript Object Notation (JSON) を使用しています。JSON では、データ値とデータ構造が両方同時にわかるように、データが階層で示されます。名前と値のペアは、`name:value` の形式で定義されます。データ階層は、名前と値のペアをブラケットで囲み、ネストする形で定義します。

DynamoDB は、ストレージ形式としてではなく、トランスポートプロトコルとしてのみ、JSON を使用しています。JSON を使用して AWS SDK が DynamoDB にデータを送信し、DynamoDB が JSON で応答します。DynamoDB は、JSON 形式でデータを永続的に保存しません。

**注記**  
JSON の詳細については、`JSON.org` ウェブサイトで「[JSON の入門](http://json.org)」を参照してください。

**Topics**
+ [

## リクエストの形式
](#Programming.LowLevelAPI.RequestFormat)
+ [

## レスポンスの形式
](#Programming.LowLevelAPI.ResponseFormat)
+ [

## データ型記述子
](#Programming.LowLevelAPI.DataTypeDescriptors)
+ [

## 数値データ
](#Programming.LowLevelAPI.Numbers)
+ [

## バイナリデータ
](#Programming.LowLevelAPI.Binary)

![\[DynamoDB の低レベル API、および AWS SDK によるプロトコルレベルのリクエストとレスポンスの処理方法。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/SDKSupport.DDBLowLevelAPI.png)


## リクエストの形式
<a name="Programming.LowLevelAPI.RequestFormat"></a>

DynamoDB 低レベル API は、HTTP(S) `POST` リクエストを入力として受け付けます。AWS SDK はこれらのリクエストを作成します。

`Pets` という名のテーブルに、`AnimalType` (パーティションキー)、`Name` (ソートキー) によって構成されるキースキーマがあるとします。これらの属性はいずれも、`string` 型になります。`Pets` から項目を取得するために、AWS SDK は次のリクエストを作成します。

```
POST / HTTP/1.1
Host: dynamodb.<region>.<domain>;
Accept-Encoding: identity
Content-Length: <PayloadSizeBytes>
User-Agent: <UserAgentString>
Content-Type: application/x-amz-json-1.0
Authorization: AWS4-HMAC-SHA256 Credential=<Credential>, SignedHeaders=<Headers>, Signature=<Signature>
X-Amz-Date: <Date> 
X-Amz-Target: DynamoDB_20120810.GetItem

{
    "TableName": "Pets",
    "Key": {
        "AnimalType": {"S": "Dog"},
        "Name": {"S": "Fido"}
    }
}
```

このリクエストに関して以下の点に注意してください。
+ `Authorization` ヘッダーには、DynamoDB がリクエストを認証するのに必要な情報が含まれています。詳細は、「*Amazon Web Services 全般のリファレンス*」の「[AWS API リクエストへの署名](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)」と「[署名バージョン 4 の署名プロセス](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)」を参照してください。
+ `X-Amz-Target` ヘッダーには、DynamoDB オペレーションの名前である `GetItem` が含まれます 。(これは、低レベル API バージョンと共に示されます。この場合は `20120810` となります。)
+ リクエストのペイロード (本文) には、JSON 形式で、オペレーションのパラメーターが含まれます。`GetItem` オペレーションでは、パラメーターは `TableName` と `Key` です。

## レスポンスの形式
<a name="Programming.LowLevelAPI.ResponseFormat"></a>

リクエストを受け取ったら、DynamoDB が処理しレスポンスを返します。前の例に示したように、HTTP レスポンスペイロードには、オペレーションからの結果が含まれます。

```
HTTP/1.1 200 OK
x-amzn-RequestId: <RequestId>
x-amz-crc32: <Checksum>
Content-Type: application/x-amz-json-1.0
Content-Length: <PayloadSizeBytes>
Date: <Date>
{
    "Item": {
        "Age": {"N": "8"},
        "Colors": {
            "L": [
                {"S": "White"},
                {"S": "Brown"},
                {"S": "Black"}
            ]
        },
        "Name": {"S": "Fido"},
        "Vaccinations": {
            "M": {
                "Rabies": {
                    "L": [
                        {"S": "2009-03-17"},
                        {"S": "2011-09-21"},
                        {"S": "2014-07-08"}
                    ]
                },
                "Distemper": {"S": "2015-10-13"}
            }
        },
        "Breed": {"S": "Beagle"},
        "AnimalType": {"S": "Dog"}
    }
}
```

この時点で、AWS SDK は、さらに処理するためにアプリケーションに応答データを返します。

**注記**  
リクエストを処理できない場合は、DynamoDB より HTTP エラーコードとメッセージが返ります。AWS SDK は、これらを例外形式でアプリケーションに伝達します。詳細については、「[DynamoDB でのエラー処理](Programming.Errors.md)」を参照してください。

## データ型記述子
<a name="Programming.LowLevelAPI.DataTypeDescriptors"></a>

低レベル DynamoDB API のプロトコルは、各属性がデータ型記述子に伴われる必要があります。*データ型記述子*は、各属性を解釈する方法を DynamoDB に伝えるトークンです。

[リクエストの形式](#Programming.LowLevelAPI.RequestFormat)と[レスポンスの形式](#Programming.LowLevelAPI.ResponseFormat)には、データ型記述子が使用されている例が示されています。`GetItem` リクエストでは、`S` キースキーマ属性 (`Pets` と `AnimalType`) に `Name` を `string` 型で指定します。`GetItem` レスポンスには、`string` (`S`)、`number` (`N`)、`map` (`M`)、`list` (`L`) 型の属性を持つ、*Pets* 項目が含まれます。

DynamoDB データ型記述子の一覧を次に示します。
+ **`S`** — 文字列
+ **`N`** — 数値
+ **`B`** — バイナリ
+ **`BOOL`** — ブール
+ **`NULL`** — Null
+ **`M`** — マップ
+ **`L`** — リスト
+ **`SS`** — 文字列セット
+ **`NS`** — 数値セット
+ **`BS`** — バイナリセット

次の表は、各データ型記述子の正しい JSON 形式を示しています。数値は精度を維持するために文字列として表されますが、ブール値と null はネイティブの JSON 型を使用することに注意してください。


| ディスクリプタ | JSON 形式 | 注意事項 | 
| --- | --- | --- | 
| S | \$1"S": "Hello"\$1 | 値は JSON 文字列です。 | 
| N | \$1"N": "123.45"\$1 | 値は文字列であり、JSON 数値ではありません。これにより、言語間で精度が維持されます。 | 
| B | \$1"B": "dGhpcyBpcyBhIHRlc3Q="\$1 | 値は base64 でエンコードされた文字列です。 | 
| BOOL | \$1"BOOL": true\$1 | 値は JSON ブール値 (true または false) で、文字列ではありません。 | 
| NULL | \$1"NULL": true\$1 | 値は null を示す JSON ブール値 true です。 | 
| M | \$1"M": \$1"Name": \$1"S": "Joe"\$1\$1\$1 | 値は、属性名と値のペアの JSON オブジェクトです。 | 
| L | \$1"L": [\$1"S": "Red"\$1, \$1"N": "5"\$1]\$1 | 値は属性値の JSON 配列です。 | 
| SS | \$1"SS": ["Red", "Blue"]\$1 | 値は文字列の JSON 配列です。 | 
| NS | \$1"NS": ["1", "2.5"]\$1 | 値は数値文字列の JSON 配列です。 | 
| BS | \$1"BS": ["U3Vubnk=", "UmFpbnk="]\$1 | 値は base64 でエンコードされた文字列の JSON 配列です。 | 

**注記**  
 DynamoDB データ型の詳細な説明については、「[データ型](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes)」を参照してください。

## 数値データ
<a name="Programming.LowLevelAPI.Numbers"></a>

プログラミング言語により、提供される JSON のサポートのレベルが異なります。場合によっては、JSONドキュメントを検証し解析するにあたり、サードパーティーのライブラリを使用することもできます。

JSON Number 型に基づいて構築されたサードパーティーライブラリもあり、`int` や `long`、`double` など独自の型を提供しています。ただし、他のデータ型に正確にマッピングされない DynamoDB のネイティブ数値データ型が使用されるため、このようなデータ型の区別が競合の原因になる可能性があります。加えて、多くの JSON ライブラリでは固定精度の数値は処理されず、小数点を含む数字列は自動的に倍精度浮動小数点データ型であると推定されます。

これらの問題を解決するために、DynamoDB ではデータ損失のない単一の数値型が用意されています。誤って倍精度の値に暗黙的変換が行われないように、DynamoDB では数値のデータ転送には文字列が使用されます。この方法によって、01、2、03 などの値を適切な順序で配置するなど、適切な並べ替えセマンティクスを維持しながら、柔軟に属性値を更新することが可能になります。

数値の精度がアプリケーションにとって重要な場合は、数値を文字列に変換してから、DynamoDB に渡します。

## バイナリデータ
<a name="Programming.LowLevelAPI.Binary"></a>

DynamoDB ではバイナリ属性がサポートされています。ただし JSON では、ネイティブではバイナリデータのエンコードがサポートされていません。リクエストでバイナリデータを送信するには、base64 形式でエンコードする必要があります。DynamoDB はリクエストを受け取ると、base64 データをバイナリに復号します。

DynamoDB で使用される base64 エンコーディングスキームは、Internet Engineering Task Force (IETF) ウェブサイトの「[RFC 4648](http://tools.ietf.org/html/rfc4648)」に記載されています。

# Python と Boto3 による Amazon DynamoDB のプログラミング
<a name="programming-with-python"></a>

このガイドは、Python で Amazon DynamoDB を使用したいと考えているプログラマーを対象としています。さまざまな抽象化レイヤー、設定管理、エラー処理、再試行ポリシーの制御、キープアライブの管理などについて説明します。

**Topics**
+ [

## Boto について
](#programming-with-python-about)
+ [

## Boto ドキュメントの使用
](#programming-with-python-documentation)
+ [

## クライアントとリソースの抽象化レイヤーを理解する
](#programming-with-python-client-resource)
+ [

## テーブルリソース batch\$1writer の使用
](#programming-with-python-batch-writer)
+ [

## クライアントレイヤーとリソースレイヤーを調べるその他のコード例
](#programming-with-python-additional-code)
+ [

## Client オブジェクトと Resource オブジェクトがセッションやスレッドとどのように相互作用するかを理解する
](#programming-with-python-sessions-thread-safety)
+ [

## Config オブジェクトのカスタマイズ
](#programming-with-python-config)
+ [

## エラー処理
](#programming-with-python-error-handling)
+ [

## ログ記録
](#programming-with-python-logging)
+ [

## イベントフック
](#programming-with-python-event-hooks)
+ [

## ページネーションとページネーター
](#programming-with-python-pagination)
+ [

## ウェイター
](#programming-with-python-waiters)

## Boto について
<a name="programming-with-python-about"></a>

Python から DynamoDB にアクセスするには、Python 用の公式 AWS SDK (一般に **Boto3** と呼ばれる) を使用します。Boto (ボトと発音) という名前は、アマゾン川に自生する淡水イルカに由来しています。Boto3 ライブラリは, ライブラリの 3 番目のメジャーバージョンであり、2015 年に初めてリリースされました。Boto3 ライブラリは、DynamoDB だけでなくすべての AWS サービスをサポートするため、非常に大きいです。このオリエンテーションは、DynamoDB に関連する Boto3 の部分のみを対象としています。

Boto は、GitHub でホストされるオープンソースプロジェクトとして AWS によって管理および公開されています。[Botocore](https://github.com/boto/botocore) と [Boto3](https://github.com/boto/boto3) の 2 つのパッケージに分かれています。
+ **Botocore** は低レベルの機能を備えています。Botocore には、クライアント、セッション、認証情報、設定、および例外クラスがあります。
+ **Boto3** は Botocore の上に構築されています。よりハイレベルで、より Python 的なインターフェイスを提供します。具体的には、DynamoDB テーブルをリソースとして公開し、低レベルのサービス指向のクライアントインターフェイスよりもシンプルで洗練されたインターフェイスを提供します。

これらのプロジェクトは GitHub でホストされているため、ソースコードを表示したり、未解決の問題を追跡したり、独自の問題を送信したりできます。

## Boto ドキュメントの使用
<a name="programming-with-python-documentation"></a>

以下のリソースを使って Boto ドキュメントを使い始めましょう。
+ まず、パッケージインストールの確実な出発点となる[「クイックスタート」セクション](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html)から始めてください。まだ Boto3 をインストールしていない場合は、そちらを参照してください (Boto3 は多くの場合、AWS Lambda などの AWS サービス内で自動的に利用可能になります)。
+ その後、ドキュメントの [DynamoDB ガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/dynamodb.html)に注目してください。テーブルの作成と削除、項目の操作、バッチ操作の実行、クエリの実行、スキャンの実行など、基本的な DynamoDB アクティビティを実行する方法を示しています。例では**リソース**インターフェイスを使用しています。`boto3.resource('dynamodb')` が表示されれば、上位レベルの**リソース**インターフェイスを使用していることがわかります。
+ ガイドを読み終えたら、[DynamoDB リファレンス](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html)を確認できます。このランディングページには、使用できるクラスとメソッドがすべて記載されています。上部には `DynamoDB.Client` クラスが表示されます。これにより、コントロールプレーンとデータプレーンのすべての操作に低レベルでアクセスできます。一番下にある `DynamoDB.ServiceResource` クラスを見てください。これは上位レベルの Python インターフェイスです。これを使用すると、テーブルを作成したり、複数のテーブルにわたってバッチ操作を実行したり、テーブル固有のアクションのために `DynamoDB.ServiceResource.Table` インスタンスを取得したりできます。

## クライアントとリソースの抽象化レイヤーを理解する
<a name="programming-with-python-client-resource"></a>

使用する 2 つのインターフェイスは、**クライアント**インターフェイスと**リソース**インターフェイスです。
+ 低レベルの**クライアント**インターフェイスは、基盤となるサービス API に 1 対 1 で対応します。DynamoDB が提供するすべての API は、クライアントを通じて利用できます。つまり、クライアントインターフェイスは完全な機能を提供できますが、多くの場合、より冗長で使い方が複雑です。
+ 上位レベルの**リソース**インターフェイスは、基盤となるサービス API と 1 対 1 で対応するわけではありません。ただし、`batch_writer` などのサービスへのアクセスが便利になります。

クライアントインターフェイスを使用して項目を挿入する例を次に示します。すべての値が、型を示すキー (文字列は 'S'、数値は 'N') と文字列としての値のマップとして渡されることに注目してください。これは DynamoDB JSON 形式と呼ばれます。

```
import boto3

dynamodb = boto3.client('dynamodb')

dynamodb.put_item(
    TableName='YourTableName',
    Item={
        'pk': {'S': 'id#1'},
        'sk': {'S': 'cart#123'},
        'name': {'S': 'SomeName'},
        'inventory': {'N': '500'},
        # ... more attributes ...
    }
)
```

リソースインターフェイスを使用した同じ `PutItem` 操作を次に示します。データ型の指定は暗黙的です。

```
import boto3

dynamodb = boto3.resource('dynamodb')

table = dynamodb.Table('YourTableName')

table.put_item(
    Item={
        'pk': 'id#1',
        'sk': 'cart#123',
        'name': 'SomeName',
        'inventory': 500,
        # ... more attributes ...
    }
)
```

必要に応じて、boto3 に用意されている `TypeSerializer` および `TypeDeserializer` クラスを使用して、通常の JSON と DynamoDB JSON の間で変換できます。

```
def dynamo_to_python(dynamo_object: dict) -> dict:
    deserializer = TypeDeserializer()
    return {
        k: deserializer.deserialize(v) 
        for k, v in dynamo_object.items()
    }  
  
def python_to_dynamo(python_object: dict) -> dict:
    serializer = TypeSerializer()
    return {
        k: serializer.serialize(v)
        for k, v in python_object.items()
    }
```

クライアントインターフェイスを使用してクエリを実行する方法は次のとおりです。クエリは JSON コンストラクトとして表現されます。キーワードの競合が発生する可能性がある場合は、変数置換が必要な `KeyConditionExpression` 文字列を使用します。

```
import boto3

client = boto3.client('dynamodb')

# Construct the query
response = client.query(
    TableName='YourTableName',
    KeyConditionExpression='pk = :pk_val AND begins_with(sk, :sk_val)',
    FilterExpression='#name = :name_val',
    ExpressionAttributeValues={
        ':pk_val': {'S': 'id#1'},
        ':sk_val': {'S': 'cart#'},
        ':name_val': {'S': 'SomeName'},
    },
    ExpressionAttributeNames={
        '#name': 'name',
    }
)
```

リソースインターフェイスを使った同じクエリ操作を短くして簡略化できます。

```
import boto3
from boto3.dynamodb.conditions import Key, Attr

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('YourTableName')

response = table.query(
    KeyConditionExpression=Key('pk').eq('id#1') & Key('sk').begins_with('cart#'),
    FilterExpression=Attr('name').eq('SomeName')
)
```

最後の例として、テーブルのおおよそのサイズ (テーブルに保持され、約 6 時間ごとに更新されるメタデータ) を取得したいとします。クライアントインターフェイスで、`describe_table()` 操作を行い、返された JSON 構造から回答を引き出します。

```
import boto3

dynamodb = boto3.client('dynamodb')

response = dynamodb.describe_table(TableName='YourTableName')
size = response['Table']['TableSizeBytes']
```

リソースインターフェイスでは、テーブルは describe 操作を暗黙的に実行し、データを属性として直接表示します。

```
import boto3

dynamodb = boto3.resource('dynamodb')

table = dynamodb.Table('YourTableName')
size = table.table_size_bytes
```

**注記**  
クライアントインターフェイスとリソースインターフェイスのどちらを使用して開発するかを検討する際、[リソースドキュメント](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html)ではリソースインターフェイスに新しい機能が追加されないことに注意してください。「AWS Python SDK チームは boto3 のリソースインターフェイスに新しい機能を追加する予定はありません。既存のインターフェイスは boto3 のライフサイクル中も引き続き動作します。顧客はクライアントインターフェイスを通じて新しいサービス機能にアクセスできます。」

## テーブルリソース batch\$1writer の使用
<a name="programming-with-python-batch-writer"></a>

上位レベルのテーブルリソースでのみ利用できる便利な機能の 1 つは、`batch_writer` です。DynamoDB はバッチ書き込み操作をサポートしており、1 つのネットワークリクエストで最大 25 件の入力または削除操作が可能です。このようなバッチ処理は、ネットワークラウンドトリップを最小限に抑えることで効率性を高めます。

低レベルのクライアントライブラリでは、`client.batch_write_item()` 操作を使用してバッチを実行します。作業は手動で 25 個のバッチに分割する必要があります。各操作の後に、未処理の項目のリストを受け取るように要求する必要もあります (書き込み操作の中には成功するものもあれば、失敗するものもあります)。その後、それらの未処理項目を後の `batch_write_item()` 操作に再度渡す必要があります。大量のボイラープレートコードがあります。

[Table.batch\$1writer](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/table/batch_writer.html) メソッドは、オブジェクトをバッチで書き込むためのコンテキストマネージャーを作成します。一度に 1 つずつ項目を書き込んでいるように見えても、内部的には項目をバッファリングしてバッチで送信するインターフェイスを提供します。また、未処理の項目の再試行も暗黙的に処理されます。

```
dynamodb = boto3.resource('dynamodb')

table = dynamodb.Table('YourTableName')

movies = # long list of movies in {'pk': 'val', 'sk': 'val', etc} format
with table.batch_writer() as writer:
    for movie in movies:
        writer.put_item(Item=movie)
```

## クライアントレイヤーとリソースレイヤーを調べるその他のコード例
<a name="programming-with-python-additional-code"></a>

次のコードサンプルリポジトリを参照して、クライアントとリソースの両方を使用してさまざまな機能の使用法を調べることもできます。
+ [AWS 公式シングルアクションのコード例。](https://docs.aws.amazon.com/code-library/latest/ug/python_3_dynamodb_code_examples.html)
+ [AWS 公式のシナリオ指向コード例。](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python)
+ [コミュニティが管理するシングルアクションのコード例。](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/python)

## Client オブジェクトと Resource オブジェクトがセッションやスレッドとどのように相互作用するかを理解する
<a name="programming-with-python-sessions-thread-safety"></a>

Resource オブジェクトはスレッドセーフではないため、スレッドやプロセス間で共有しないでください。詳細については、[Resource に関するガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html#multithreading-or-multiprocessing-with-resources)を参照してください。

これとは対照的に、Client オブジェクトは、特定の高度な機能を除いて、通常はスレッドセーフです。詳細については、[Clients に関するガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html#multithreading-or-multiprocessing-with-clients)を参照してください。

Session オブジェクトはスレッドセーフではありません。そのため、マルチスレッド環境で Client または Resource を作成するたびに、まず、新しい Session を作成してから、その Session から Client または Resource を作成する必要があります。詳細については、[Sessions に関するガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/session.html#multithreading-or-multiprocessing-with-sessions)を参照してください。

`boto3.resource()` を呼び出すとき、暗黙的にデフォルトの Session を使用することになります。これはシングルスレッドのコードを書くのに便利です。マルチスレッドのコードを書くときには、まず、スレッドごとに新しい Session を構築し、その Session からリソースを取得します。

```
# Explicitly create a new Session for this thread 
session = boto3.Session()
dynamodb = session.resource('dynamodb')
```

## Config オブジェクトのカスタマイズ
<a name="programming-with-python-config"></a>

Client または Resource オブジェクトを作成するときに、オプションの名前付きパラメータを渡して動作をカスタマイズできます。`config` という名前のパラメータは、さまざまな機能をアンロックします。これは `botocore.client.Config` のインスタンスであり、[Config のリファレンスドキュメント](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html)には、ユーザーが制御できるすべての情報が記載されています。[設定ガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html)には、概要がわかりやすく書かれています。

**注記**  
これらの動作設定の多くは、Session レベル、AWS 構成ファイル内、または環境変数として変更できます。

**タイムアウトの設定**

カスタム設定の用途の 1 つは、ネットワークの動作を調整することです。
+ **connect\$1timeout (float または int)** — 接続を試みたときにタイムアウト例外がスローされるまでの時間 (秒単位)。デフォルト値は 60 秒です。
+ **read\$1timeout (float または int)** — 接続からの読み取りを試みたときにタイムアウト例外がスローされるまでの時間 (秒単位)。デフォルト値は 60 秒です。

DynamoDB では 60 秒のタイムアウトは過剰です。つまり、一時的なネットワークの不具合により、クライアントが再試行できるようになるまでに 1 分間の遅延が生じます。次のコードはタイムアウトを 1 秒に短縮します。

```
import boto3
from botocore.config import Config

my_config = Config(
   connect_timeout = 1.0,
   read_timeout = 1.0
)
dynamodb = boto3.resource('dynamodb', config=my_config)
```

タイムアウトの詳細については、「[レイテンシーを考慮した DynamoDB アプリケーションのための AWS Java SDK HTTP リクエスト設定のチューニング](https://aws.amazon.com/blogs/database/tuning-aws-java-sdk-http-request-settings-for-latency-aware-amazon-dynamodb-applications/)」を参照してください。Java SDK には Python よりも多くのタイムアウト設定があることに注意してください。

**キープアライブの設定**

botocore 1.27.84 以降を使用している場合は、**TCP キープアライブ**を制御することもできます。
+ **tcp\$1keepalive** (bool) - `True` に設定された場合、新しい接続の作成時に使用される TCP キープアライブソケットオプションを有効にします (デフォルトは `False`)。これは botocore 1.27.84 以降でのみ使用可能です。

TCP キープアライブを `True` に設定すると、平均レイテンシーを減らすことができます。以下は、適切な botocore バージョンを使用している場合に TCP キープアライブを条件付きで true に設定するサンプルコードです。

```
import botocore
import boto3
from botocore.config import Config
from distutils.version import LooseVersion

required_version = "1.27.84"
current_version = botocore.__version__

my_config = Config(
   connect_timeout = 0.5,
   read_timeout = 0.5
)
if LooseVersion(current_version) > LooseVersion(required_version):
    my_config = my_config.merge(Config(tcp_keepalive = True))

dynamodb = boto3.resource('dynamodb', config=my_config)
```

**注記**  
TCP キープアライブは HTTP キープアライブとは異なります。TCP キープアライブでは、接続を維持してドロップを即座に検出するために、基盤となるオペレーティングシステムからソケット接続を介して小さなパケットが送信されます。HTTP キープアライブでは、基盤となるソケット上に構築された Web 接続が再利用されます。HTTP キープアライブは boto3 では常に有効になっています。

アイドル状態の接続を維持できる時間には制限があります。接続がアイドル状態で、次のリクエストではすでに確立されている接続を使いたい場合は、定期的に (たとえば 1 分ごとに) リクエストを送信することを検討してください。

**再試行の設定**

この設定では、希望する再試行動作を指定できる **retries** という辞書も使用できます。SDK がエラーを受信し、そのエラーが一時的なタイプの場合、SDK 内で再試行が行われます。エラーが内部で再試行された場合 (そして再試行によって最終的に成功の応答が得られた場合)、呼び出し側のコードから見ると、エラーは発生せず、レイテンシーがわずかに増加するだけです。指定できる値は次のとおりです。
+ **max\$1attempts** — 1 回のリクエストで行われる最大再試行回数を表す整数。たとえば、この値を 2 に設定すると、最初のリクエストから最大 2 回リクエストが再試行されます。この値を 0 に設定すると、最初のリクエスト以降は再試行されません。
+ **total\$1max\$1attempts** — 1 回のリクエストで行われる最大再試行合計回数を表す整数。これには最初のリクエストが含まれるため、値が 1 の場合はリクエストが再試行されないことを示します。`total_max_attempts` と `max_attempts` の両方が指定された場合、`total_max_attempts` が優先されます。`total_max_attempts` は、`AWS_MAX_ATTEMPTS` 環境変数と `max_attempts` 設定ファイルの値にマップされるので、`max_attempts` より優先されます。
+ **mode** — botocore が使用すべき再試行モードの種類を表す文字列。次の値を指定できます。
  + **legacy** — デフォルトモード。最初の再試行は 50 ms 待機し、基本係数 2 でエクスポネンシャルバックオフを使用します。DynamoDB の場合、最大試行回数は合計 10 回です (上記でオーバーライドされない限り)。
**注記**  
エクスポネンシャルバックオフでは、最後の試行ではほぼ 13 秒待機します。
  + **standard** — 他の AWS SDK との整合性が高いことから、standard と名付けられています。最初の再試行時には、0 ミリ秒から 1,000 ミリ秒までのランダムな時間だけ待ちます。再試行が必要な場合は、0 ミリ秒から 1,000 ミリ秒までの別のランダムな時間を選択し、その値に 2 を掛けます。さらに再試行が必要な場合は、同じようにランダムな時間を選択し、これに 4 を掛け、試行を続けます。各待機時間の上限は 20 秒です。このモードは、検出された障害条件の数が `legacy` モードよりも多い場合に再試行を実行します。DynamoDB の場合、最大試行回数は合計 3 回です (上記でオーバーライドされない限り)。
  + **adaptive** – standard モードのすべての機能を含みながら、クライアント側の自動スロットリングを含む実験的な再試行モード。適応型レート制限を使用すると、SDK は AWS のサービスの容量をより適切に処理するために、リクエストの送信速度を遅くすることができます。これは暫定モードであり、動作が変わる可能性があります。

これらの再試行モードの拡張定義は、[再試行ガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/retries.html)と [SDK リファレンスの「再試行動作」トピック](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html)に記載されています。

次の例は、`legacy` 再試行ポリシーを明示的に使用して、合計リクエスト 3 回 (再試行 2 回) までにした例です。

```
import boto3
from botocore.config import Config

my_config = Config(
   connect_timeout = 1.0,
   read_timeout = 1.0,
   retries = {
     'mode': 'legacy',
     'total_max_attempts': 3
   }
)
dynamodb = boto3.resource('dynamodb', config=my_config)
```

DynamoDB は可用性が高く、レイテンシーが低いシステムであるため、組み込みの再試行ポリシーで許可されているよりも積極的に再試行の速度を上げる必要がある場合があります。boto3 に頼って暗黙的な再試行を行うのではなく、最大試行回数を 0 に設定し、自分で例外をキャッチし、必要に応じて独自のコードから再試行することで、独自の再試行ポリシーを実装できます。

独自の再試行ポリシーを管理する場合は、スロットルとエラーを区別しておきましょう。
+ **スロットル** (`ProvisionedThroughputExceededException` または `ThrottlingException` で示される) は、DynamoDB テーブルまたはパーティションの読み取り容量または書き込み容量を超過したことを通知する正常なサービスを示します。1 ミリ秒が経過するごとに、読み取りまたは書き込み容量が少しずつ増えるため、すぐに (50 ミリ秒ごとなど) 再試行して、新しく解放された容量へのアクセスを試みることができます。スロットルについては、エクスポネンシャルバックオフは特に必要ありません。軽量で DynamoDB が返しやすく、リクエストごとの課金も発生しないためです。エクスポネンシャルバックオフでは、すでに最長の待機時間が過ぎたクライアントスレッドの遅延をさらに長くしていくため、統計的に p50 と p99 が外側に広がります。
+ **エラー** (`InternalServerError` または `ServiceUnavailable` などによって示される) は、サービスに一時的な問題があることを示します。これはテーブル全体の場合もあれば、読み取り元または書き込み先のパーティションだけに関する場合もあります。エラーが発生した場合は、再試行の前に少し長く一時停止し (250 ミリ秒や 500 ミリ秒など)、ジッターを使って再試行をずらすことができます。

**最大プール接続数の設定**

最後に、この構成では接続プールのサイズを制御できます。
+ **max\$1pool\$1connections (int)** — 接続プールに保持できる最大接続数。この値が設定されていない場合、デフォルト値の 10 が使用されます。

このオプションは、プールして再利用できるように保持する HTTP 接続の最大数を制御します。Session ごとに異なるプールが保持されます。10 個を超えるスレッドが、同じ Session から構築されたクライアントやリソースに対して実行されることが予想される場合は、プールされた接続を使用する他のスレッドに対してスレッドが待機する必要がないように、この値を増やすことを検討すべきです。

```
import boto3
from botocore.config import Config

my_config = Config(
   max_pool_connections = 20
)

# Setup a single session holding up to 20 pooled connections
session = boto3.Session(my_config)

# Create up to 20 resources against that session for handing to threads
# Notice the single-threaded access to the Session and each Resource
resource1 = session.resource('dynamodb')
resource2 = session.resource('dynamodb')
# etc
```

## エラー処理
<a name="programming-with-python-error-handling"></a>

Boto3 では AWS サービスの例外がすべて静的に定義されているわけではありません。これは、AWS サービスのエラーや例外は大きく異なり、変更される可能性があるためです。Boto3 はすべてのサービス例外を `ClientError` としてラップし、詳細を構造化された JSON として公開します。例えば、エラーレスポンスは以下のような構造になっているかもしれません。

```
{
    'Error': {
        'Code': 'SomeServiceException',
        'Message': 'Details/context around the exception or error'
    },
    'ResponseMetadata': {
        'RequestId': '1234567890ABCDEF',
        'HostId': 'host ID data will appear here as a hash',
        'HTTPStatusCode': 400,
        'HTTPHeaders': {'header metadata key/values will appear here'},
        'RetryAttempts': 0
    }
}
```

次のコードは、すべての `ClientError` 例外をキャッチし、`Error` 内の `Code` の文字列値を調べて実行するアクションを決定します。

```
import botocore
import boto3

dynamodb = boto3.client('dynamodb')

try:
    response = dynamodb.put_item(...)

except botocore.exceptions.ClientError as err:
    print('Error Code: {}'.format(err.response['Error']['Code']))
    print('Error Message: {}'.format(err.response['Error']['Message']))
    print('Http Code: {}'.format(err.response['ResponseMetadata']['HTTPStatusCode']))
    print('Request ID: {}'.format(err.response['ResponseMetadata']['RequestId']))

    if err.response['Error']['Code'] in ('ProvisionedThroughputExceededException', 'ThrottlingException'):
        print("Received a throttle")
    elif err.response['Error']['Code'] == 'InternalServerError':
        print("Received a server error")
    else:
        raise err
```

一部の (すべてではない) 例外コードは最上位クラスとして実装されています。これらを直接処理することもできます。Client インターフェイスを使用する場合、これらの例外はクライアントに動的に入力され、以下のようにクライアントインスタンスを使用してこれらの例外をキャッチします。

```
except ddb_client.exceptions.ProvisionedThroughputExceededException:
```

Resource インターフェイスを使用しているときには、以下のように、`.meta.client` を使用してリソースから基盤となる Client までトラバースして例外にアクセスする必要があります。

```
except ddb_resource.meta.client.exceptions.ProvisionedThroughputExceededException:
```

マテリアライズド例外タイプのリストを確認するには、リストを動的に生成できます。

```
ddb = boto3.client("dynamodb")
print([e for e in dir(ddb.exceptions) if e.endswith('Exception') or e.endswith('Error')])
```

条件式を使用して書き込み操作を行う場合、式が失敗した場合にその項目の値をエラーレスポンスで返すようにリクエストできます。

```
try:
    response = table.put_item(
        Item=item,
        ConditionExpression='attribute_not_exists(pk)',
        ReturnValuesOnConditionCheckFailure='ALL_OLD'
    )
except table.meta.client.exceptions.ConditionalCheckFailedException as e:
    print('Item already exists:', e.response['Item'])
```

エラー処理と例外について詳しくは、以下を参照してください。
+ エラー処理技術の詳細については、[エラー処理に関する boto3 ガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/error-handling.html)を参照してください。
+ [DynamoDB 開発者ガイドのプログラミングエラーに関するセクション](Programming.Errors.md)には、発生する可能性のあるエラーが記載されています。
+ [API リファレンスの「一般的なエラー」セクション](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/CommonErrors.html)。
+ 各 API 操作のドキュメントには、呼び出しによって発生する可能性のあるエラー (例: [BatchWriteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html)) が記載されています。

## ログ記録
<a name="programming-with-python-logging"></a>

boto3 ライブラリは Python の組み込みロギングモジュールと統合されており、セッション中に何が起こるかを追跡できます。ロギングレベルを制御するには、ロギングモジュールを設定します。

```
import logging

logging.basicConfig(level=logging.INFO)
```

これにより、`INFO` 以上のレベルのメッセージを記録するようにルートロガーが設定されます。レベルよりも重大度の低いロギングメッセージは無視されます。ロギングレベルには、`DEBUG`、`INFO`、`WARNING`、`ERROR`、および `CRITICAL` があります。デフォルトは `WARNING` です。

boto3 のロガーは階層構造になっています。ライブラリはいくつかの異なるロガーを使用しており、それぞれがライブラリの異なる部分に対応しています。それぞれの動作を個別に制御できます。
+ **boto3**: boto3 モジュールのメインロガー。
+ **botocore**: botocore パッケージのメインロガー。
+ **botocore.auth**: リクエストの AWS 署名作成を記録するために使用されます。
+ **botocore.credentials**: 認証情報の取得と更新のプロセスを記録するために使用されます。
+ **botocore.endpoint**: ネットワーク経由で送信される前に、リクエストの作成を記録するために使用されます。
+ **botocore.hooks**: ライブラリでトリガーされたイベントの記録に使用されます。
+ **botocore.loaders**: AWS サービスモデルの一部がロードされたときの記録に使用されます。
+ **botocore.parsers**: AWS サービスレスポンスを解析する前に記録するために使用されます。
+ **botocore.retryhandler**: AWS サービスリクエストの再試行の処理を記録するために使用されます (レガシーモード)。
+ **botocore.retries.standard**: AWS サービスリクエストの再試行の処理を記録するために使用されます (standard または adaptive モード)。
+ **botocore.utils**: ライブラリ内のさまざまなアクティビティを記録するために使用されます。
+ **botocore.waiter**: 特定の状態になるまで AWS サービスにポーリングするウェイターの機能をログに記録するために使用されます。

他のライブラリもログに記録されます。内部的には、boto3 は HTTP 接続処理にサードパーティの urllib3 を使用しています。レイテンシーが重要な場合は、ログを監視して、urllib3 が新しい接続を確立したり、アイドル状態の接続を閉じたりするタイミングを確認することで、プールが十分に利用されているかどうかを確認できます。
+ **urllib3.connectionpool:** 接続プールの処理イベントを記録するために使用されます。

以下のコードスニペットは、ほとんどのロギングを `INFO` に設定し、エンドポイントと接続プールのアクティビティの記録には `DEBUG` に設定しています。

```
import logging

logging.getLogger('boto3').setLevel(logging.INFO)
logging.getLogger('botocore').setLevel(logging.INFO)
logging.getLogger('botocore.endpoint').setLevel(logging.DEBUG)
logging.getLogger('urllib3.connectionpool').setLevel(logging.DEBUG)
```

## イベントフック
<a name="programming-with-python-event-hooks"></a>

Botocore は実行中のさまざまな段階でイベントを発生させます。これらのイベントのハンドラーを登録すると、イベントが発生するたびにハンドラーが呼び出されます。これにより、内部を変更しなくても botocore の動作を拡張できます。

例えば、アプリケーションの DynamoDB テーブルで `PutItem` 操作が呼び出されるたびに記録しておきたいとしましょう。`'provide-client-params.dynamodb.PutItem'` イベントに登録すると、関連する Session で `PutItem` 操作が呼び出されるたびにキャッチしてログに記録できます。例を示します。

```
import boto3
import botocore
import logging

def log_put_params(params, **kwargs):
    if 'TableName' in params and 'Item' in params:
        logging.info(f"PutItem on table {params['TableName']}: {params['Item']}")

logging.basicConfig(level=logging.INFO)

session = boto3.Session()
event_system = session.events

# Register our interest in hooking in when the parameters are provided to PutItem
event_system.register('provide-client-params.dynamodb.PutItem', log_put_params)

# Now, every time you use this session to put an item in DynamoDB,
# it will log the table name and item data.
dynamodb = session.resource('dynamodb')
table = dynamodb.Table('YourTableName')
table.put_item(
    Item={
        'pk': '123',
        'sk': 'cart#123',
        'item_data': 'YourItemData',
        # ... more attributes ...
    }
)
```

ハンドラー内で、パラメータをプログラムで操作して動作を変更することもできます。

```
params['TableName'] = "NewTableName"
```

イベントについて詳しくは、[イベントに関する botocore ドキュメント](https://botocore.amazonaws.com/v1/documentation/api/latest/topics/events.html)と、[イベントに関する boto3 ドキュメント](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/events.html)を参照してください。

## ページネーションとページネーター
<a name="programming-with-python-pagination"></a>

Query や Scan などの一部のリクエストでは、1 回のリクエストで返されるデータのサイズが制限され、後続のページを取得するにはリクエストを繰り返し行う必要があります。

各ページで読み取られる項目の最大数は、`limit` パラメータを使用して制御できます。例えば、最後の 10 項目だけが必要な場合、`limit` を使用して最後の 10 項目だけを取得できます。制限は、フィルタリングが適用される前にテーブルから読み取られる量であることに注意してください。フィルタリング後に正確に 10 を指定する方法はありません。事前にフィルター処理される回数を制御し、実際に 10 個を取得した時点でクライアント側で確認することしかできません。制限にかかわらず、すべての応答の最大サイズは常に 1 MB です。

応答に `LastEvaluatedKey` が含まれている場合、それは件数またはサイズの制限に達したために応答が終了したことを示します。キーはレスポンスで評価された最後のキーです。この `LastEvaluatedKey` を取得して，フォローアップコールに `ExclusiveStartKey` として渡すと、その開始点から次のチャンクを読み取ることができます。`LastEvaluatedKey` が返されないということは、Query または Scan に一致するアイテムがもうないということです。

以下は、1 ページあたり最大 100 個の項目を読み込み、すべての項目が読み込まれるまでループする単純な例です (Resource インターフェイスを使用していますが、Client インターフェイスでも同じパターンです)。

```
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('YourTableName')

query_params = {
    'KeyConditionExpression': Key('pk').eq('123') & Key('sk').gt(1000),
    'Limit': 100
}

while True:
    response = table.query(**query_params)

    # Process the items however you like
    for item in response['Items']:
        print(item)

    # No LastEvaluatedKey means no more items to retrieve
    if 'LastEvaluatedKey' not in response:
        break

    # If there are possibly more items, update the start key for the next page
    query_params['ExclusiveStartKey'] = response['LastEvaluatedKey']
```

便宜上、boto3 はページネーターを使ってこれを行うことができます。ただし、Client インターフェイスでのみ機能します。以下はページネーターを使うように書き直されたコードです。

```
import boto3

dynamodb = boto3.client('dynamodb')

paginator = dynamodb.get_paginator('query')

query_params = {
    'TableName': 'YourTableName',
    'KeyConditionExpression': 'pk = :pk_val AND sk > :sk_val',
    'ExpressionAttributeValues': {
        ':pk_val': {'S': '123'},
        ':sk_val': {'N': '1000'},
    },
    'Limit': 100
}

page_iterator = paginator.paginate(**query_params)

for page in page_iterator:
    # Process the items however you like
    for item in page['Items']:
        print(item)
```

詳細については、[ページネーターに関するガイド](https://botocore.amazonaws.com/v1/documentation/api/latest/topics/events.html)と [DynamoDB.Paginator.Query の API リファレンス](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/paginator/Query.html)を参照してください。

**注記**  
ページネーターには、`MaxItems`、`StartingToken`、および `PageSize` という名前の独自の構成設定もあります。DynamoDB でページ分割を行う場合は、これらの設定は無視してください。

## ウェイター
<a name="programming-with-python-waiters"></a>

ウェイターは、処理が完了するのを待ってから次の処理を進めることができます。現在のところ、サポートしているのはテーブルが作成または削除されるのを待つことだけです。バックグラウンドでは、ウェイター操作は 20 秒ごとに最大 25 回までチェックを行います。これは自分で行うこともできますが、オートメーションを書くときはウェイターを使うのが便利です。

次のコードは、特定のテーブルが作成されるまで待機する方法を示しています。

```
# Create a table, wait until it exists, and print its ARN
response = client.create_table(...)
waiter = client.get_waiter('table_exists')
waiter.wait(TableName='YourTableName')
print('Table created:', response['TableDescription']['TableArn']
```

詳細については、[ウェイターに関するガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html#waiters)と[ウェイターに関するリファレンス](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#waiters)を参照してください。

# JavaScript による Amazon DynamoDB のプログラミング
<a name="programming-with-javascript"></a>

このガイドは、JavaScript で Amazon DynamoDB を使用したいと考えているプログラマーを対象としています。AWS SDK for JavaScript、利用可能な抽象化レイヤー、接続の設定、エラー処理、再試行ポリシーの定義、キープアライブの管理などについて説明します。

**Topics**
+ [

## AWS SDK for JavaScript について
](#programming-with-javascript-about)
+ [

## AWS SDK for JavaScript V3 を使用する
](#programming-with-javascript-using-the-sdk)
+ [

## JavaScript のドキュメントを参照する
](#programming-with-javascript-documentation)
+ [

## 抽象化レイヤー
](#programming-with-javascript-abstraction-layers)
+ [

## marshall ユーティリティ関数を使用する
](#programming-with-javascript-using-marshall-utility)
+ [

## 項目の読み込み
](#programming-with-javascript-reading-items)
+ [

## 条件付きの書き込み
](#programming-with-javascript-conditional-writes)
+ [

## ページ分割
](#programming-with-javascript-pagination)
+ [

## 構成を指定する
](#programming-with-javascript-config)
+ [

## ウェイター
](#programming-with-javascript-waiters)
+ [

## エラー処理
](#programming-with-javascript-error-handling)
+ [

## ログ記録
](#programming-with-javascript-logging)
+ [

## 考慮事項
](#programming-with-javascript-considerations)

## AWS SDK for JavaScript について
<a name="programming-with-javascript-about"></a>

AWS SDK for JavaScript を使用すると、ブラウザスクリプトまたは Node.js のいずれかで AWS のサービス にアクセスできます。このドキュメントでは、最新バージョンの SDK (V3) を主に取り上げます。AWS SDK for JavaScript V3 は、AWS が管理する[オープンソースのプロジェクトであり、GitHub でホスト](https://github.com/aws/aws-sdk-js-v3)されています。Issue や Feature のリクエストは公開されており、GitHub リポジトリの [Issues] ページからアクセスできます。

JavaScript V2 は V3 と似ていますが、構文が違います。V3 の方がモジュール性が高いため、依存関係をより小さくして配布することが容易で、TypeScript のサポートも充実しています。最新バージョンの SDK を使用することをお勧めします。

## AWS SDK for JavaScript V3 を使用する
<a name="programming-with-javascript-using-the-sdk"></a>

Node Package Manager を使用して SDK を Node.js アプリケーションに追加できます。以下の例は、DynamoDB の操作に一般的に使われる SDK パッケージの追加方法を示しています。
+ `npm install @aws-sdk/client-dynamodb`
+ `npm install @aws-sdk/lib-dynamodb`
+ `npm install @aws-sdk/util-dynamodb`

パッケージをインストールすると、package.json プロジェクトファイルの依存関係セクションに参照が追加されます。新しい ECMAScript モジュール構文を使用することもできます。これら 2 つのアプローチの詳細については、「考慮事項」セクションを参照してください。

## JavaScript のドキュメントを参照する
<a name="programming-with-javascript-documentation"></a>

まずは、JavaScript のドキュメントを確認しましょう。以下のリソースを参照してください。
+ JavaScript の主要ドキュメントについては、「[デベロッパーガイド](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html)」を参照してください。インストール手順は「**Setting up**」セクションに記載されています。
+ [API リファレンス](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/)ドキュメントを参照し、使用可能なすべてのクラスとメソッドを確認してください。
+ SDK for JavaScript は DynamoDB 以外にも数多くの AWS のサービス をサポートしています。以下の手順にそって、DynamoDB の特定の API カバレッジを調べてください。

  1. **[Services]** から **[DynamoDB and Libraries]** を選択します。これは、低レベルクライアントをドキュメント化したものです。

  1. **lib-dynamodb** を選択します。これは、高レベルクライアントをドキュメント化したものです。これら 2 つのクライアントは、2 つの異なる抽象化レイヤーを表しています。任意で選んで使用できます。抽象レイヤーの詳細については、以下のセクションを参照してください。

## 抽象化レイヤー
<a name="programming-with-javascript-abstraction-layers"></a>

SDK for JavaScript V3 には、低レベルのクライアント (`DynamoDBClient`) と高レベルのクライアント (`DynamoDBDocumentClient`) があります。

**Topics**
+ [

### 低レベルクライアント (`DynamoDBClient`)
](#programming-with-javascript-low-level-client)
+ [

### 高レベルクライアント (`DynamoDBDocumentClient`)
](#programming-with-javascript-high-level-client)

### 低レベルクライアント (`DynamoDBClient`)
<a name="programming-with-javascript-low-level-client"></a>

低レベルクライアントでは、基盤のワイヤプロトコルが別段抽象化されません。通信をあらゆる側面から完全に制御できますが、抽象化されていないため、項目定義の提供などの操作は、DynamoDB JSON 形式を使って行う必要があります。

以下の例に示すように、この形式ではデータ型を明示的に指定する必要があります。*S* は文字列値を示し、*N* は数値を示します。ネットワーク上の数値は、精度が損なわれないように、必ず数値型としてタグ付けされた文字列として送信されます。低レベルの API コールには、`PutItemCommand` や `GetItemCommand` などの命名規則があります。

次の例では、低レベルクライアントを使用し、DynamoDB JSON で `Item` を定義しています。

```
const { DynamoDBClient, PutItemCommand } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({});

async function addProduct() {
  const params = {
    TableName: "products",
    Item: {
      "id": { S: "Product01" },
      "description": { S: "Hiking Boots" },
      "category": { S: "footwear" },
      "sku": { S: "hiking-sku-01" },
      "size": { N: "9" }
    }
  };

  try {
    const data = await client.send(new PutItemCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}
addProduct();
```

### 高レベルクライアント (`DynamoDBDocumentClient`)
<a name="programming-with-javascript-high-level-client"></a>

高レベルの DynamoDB ドキュメントクライアントには、データを手動でマーシャリングする必要がない、標準の JavaScript オブジェクトを使用して直接読み書きできるなど、便利な機能が組み込まれています。[`lib-dynamodb` のドキュメント](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-lib-dynamodb/)には、利点が一覧で紹介されています。

`DynamoDBDocumentClient` をインスタンス化するには、まず、低レベルの `DynamoDBClient` を構築し、それを `DynamoDBDocumentClient` でラップします。関数の命名規則は 2 つのパッケージ間で若干異なります。例えば、低レベルでは `PutItemCommand` を使用し、高レベルでは `PutCommand` を使用します。名前が違えば、両方の関数セットが同じコンテキストで共存可能です。つまり、同一スクリプト内で両方を組み合わせることができます。

```
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb");

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(client);

async function addProduct() {
  const params = {
    TableName: "products",
    Item: {
      id: "Product01",
      description: "Hiking Boots",
      category: "footwear",
      sku: "hiking-sku-01",
      size: 9,
    },
  };

  try {
    const data = await docClient.send(new PutCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}

addProduct();
```

`GetItem`、`Query`、`Scan` などの API オペレーションを使用して項目を読み取る場合の使用パターンは同じです。

## marshall ユーティリティ関数を使用する
<a name="programming-with-javascript-using-marshall-utility"></a>

低レベルクライアントを使用して、データ型を自分でマーシャリングまたはアンマーシャリングできます。ユーティリティパッケージ [util-dynamodb](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-util-dynamodb/) には、JSON を受け入れて DynamoDB JSON を生成する `marshall()` ユーティリティ関数と、その逆を行う `unmarshall()` 関数があります。次の例では、低レベルクライアントを使用し、`marshall()` を呼び出してデータマーシャリングを処理しています。

```
const { DynamoDBClient, PutItemCommand } = require("@aws-sdk/client-dynamodb");
const { marshall } = require("@aws-sdk/util-dynamodb");

const client = new DynamoDBClient({});

async function addProduct() {
  const params = {
    TableName: "products",
    Item: marshall({
      id: "Product01",
      description: "Hiking Boots",
      category: "footwear",
      sku: "hiking-sku-01",
      size: 9,
    }),
  };

  try {
    const data = await client.send(new PutItemCommand(params));
  } catch (error) {
    console.error("Error:", error);
  }
}
addProduct();
```

## 項目の読み込み
<a name="programming-with-javascript-reading-items"></a>

DynamoDB から項目を 1 つ読み込むには、`GetItem` API オペレーションを使用します。`PutItem` コマンドと同様に、低レベルのクライアントまたは高レベルのドキュメントクライアントのいずれかを選んで使用できます。以下の例は、高レベルのドキュメントクライアントを使用して項目を取得する方法を示しています。

```
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocumentClient, GetCommand } = require("@aws-sdk/lib-dynamodb");

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(client);

async function getProduct() {
  const params = {
    TableName: "products",
    Key: {
      id: "Product01",
    },
  };

  try {
    const data = await docClient.send(new GetCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}

getProduct();
```

`Query` API オペレーションを使用して、複数の項目を読み込みます。低レベルのクライアントまたはドキュメントクライアントを使用できます。以下の例では、高レベルのドキュメントクライアントを使用しています。

```
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const {
  DynamoDBDocumentClient,
  QueryCommand,
} = require("@aws-sdk/lib-dynamodb");

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(client);

async function productSearch() {
  const params = {
    TableName: "products",
    IndexName: "GSI1",
    KeyConditionExpression: "#category = :category and begins_with(#sku, :sku)",
    ExpressionAttributeNames: {
      "#category": "category",
      "#sku": "sku",
    },
    ExpressionAttributeValues: {
      ":category": "footwear",
      ":sku": "hiking",
    },
  };

  try {
    const data = await docClient.send(new QueryCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}

productSearch();
```

## 条件付きの書き込み
<a name="programming-with-javascript-conditional-writes"></a>

DynamoDB の書き込みオペレーションでは、論理条件式を指定できます。条件式が true と評価されないと、書き込みは続行されません。条件の評価が true にならなかった場合は、例外が生成されます。条件式では、該当する項目が既に存在するかどうかや、その属性が特定の制約に一致するかどうかを確認できます。

`ConditionExpression = "version = :ver AND size(VideoClip) < :maxsize" `

条件式が失敗した場合は、`ReturnValuesOnConditionCheckFailure` を使用して、条件を満たさなかった項目をエラーレスポンスに含めるようにリクエストできるため、問題の原因究明に役立ちます。詳細については、「[Handle conditional write errors in high concurrency scenarios with Amazon DynamoDB](https://aws.amazon.com/blogs/database/handle-conditional-write-errors-in-high-concurrency-scenarios-with-amazon-dynamodb/)」を参照してください。

```
try {
      const response = await client.send(new PutCommand({
          TableName: "YourTableName",
          Item: item,
          ConditionExpression: "attribute_not_exists(pk)",
          ReturnValuesOnConditionCheckFailure: "ALL_OLD"
      }));
  } catch (e) {
      if (e.name === 'ConditionalCheckFailedException') {
          console.log('Item already exists:', e.Item);
      } else {
          throw e;
      }
  }
```

JavaScript SDK V3 のその他の使用法を示す追加のコード例は、[JavaScript SDK V3 ドキュメント](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_dynamodb_code_examples.html)と [DynamoDB-SDK-Examples GitHub リポジトリ](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/node.js)でご覧ください。

## ページ分割
<a name="programming-with-javascript-pagination"></a>

**Topics**
+ [

### 便利な `paginateScan` メソッドを使用する
](#using-the-paginatescan-convenience-method)

`Scan` や `Query` などの読み取りリクエストでは、データセット内の複数の項目が返される場合があります。`Limit` パラメータを指定して `Scan` や `Query` を実行した場合は、システムで多数の項目が全部読み取られた後、一部のレスポンスが送信されます。追加の項目を取得するには、ページ分割が必要です。

システムは、1 回のリクエストにつき最大 1 MB のデータのみを読み取ります。`Filter` 式を含めた場合も、システムは最大 1 MB のデータをディスクから読み取りますが、その 1 MB の中から、指定したフィルターに一致した項目だけを返します。フィルターオペレーションでは 1 ページあたりに返される項目数が 0 個になる場合もありますが、それでも、さらにページ分割をしないと、最後まで検索できません。

データの取得を継続するには、レスポンスで `LastEvaluatedKey` を探し、それを後続のリクエストの `ExclusiveStartKey` パラメータに指定する必要があります。これが、以下の例に示すように、ブックマークの役割を果たします。

**注記**  
この例では、1 回目の反復で null `lastEvaluatedKey` が `ExclusiveStartKey` として渡されています。これは許容されています。

`LastEvaluatedKey` を使用する例:

```
const { DynamoDBClient, ScanCommand } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({});

async function paginatedScan() {
  let lastEvaluatedKey;
  let pageCount = 0;

  do {
    const params = {
      TableName: "products",
      ExclusiveStartKey: lastEvaluatedKey,
    };

    const response = await client.send(new ScanCommand(params));
    pageCount++;
    console.log(`Page ${pageCount}, Items:`, response.Items);
    lastEvaluatedKey = response.LastEvaluatedKey;
  } while (lastEvaluatedKey);
}

paginatedScan().catch((err) => {
  console.error(err);
});
```

### 便利な `paginateScan` メソッドを使用する
<a name="using-the-paginatescan-convenience-method"></a>



SDK には、`paginateScan` と `paginateQuery` という便利なメソッドがあります。これらは、ページ分割を自動で行い、繰り返しのリクエストをバックグラウンドで処理してくれます。標準の `Limit` パラメータを使用して、1 回のリクエストで読み取る項目の最大数を指定します。

```
const { DynamoDBClient, paginateScan } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({});

async function paginatedScanUsingPaginator() {
  const params = {
    TableName: "products",
    Limit: 100
  };

  const paginator = paginateScan({client}, params);

  let pageCount = 0;

  for await (const page of paginator) {
    pageCount++;
    console.log(`Page ${pageCount}, Items:`, page.Items);
  }
}

paginatedScanUsingPaginator().catch((err) => {
  console.error(err);
});
```

**注記**  
テーブルが小さくない限り、テーブル全体のスキャンを定期的に実行することは、アクセスパターンとして推奨されません。

## 構成を指定する
<a name="programming-with-javascript-config"></a>

**Topics**
+ [

### タイムアウトの設定
](#programming-with-javascript-config-timeouts)
+ [

### キープアライブの設定
](#programming-with-javascript-config-keep-alive)
+ [

### 再試行の設定
](#programming-with-javascript-config-retries)

`DynamoDBClient` を設定する際に、構成オブジェクトをコンストラクタに渡すことで、さまざまな構成オーバーライドを指定できます。例えば、接続先のリージョン (呼び出し側のコンテキストが把握していない場合) や、使用するエンドポイント URL を指定できます。開発目的で DynamoDB Local インスタンスをターゲットにする場合に便利です。

```
const client = new DynamoDBClient({
  region: "eu-west-1",
  endpoint: "http://localhost:8000",
});
```

### タイムアウトの設定
<a name="programming-with-javascript-config-timeouts"></a>

DynamoDB では、クライアント/サーバー通信に HTTPS を使用します。HTTP レイヤーの一部の側面は、`NodeHttpHandler` オブジェクトを指定することで制御できます。例えば、主要なタイムアウト値である `connectionTimeout` や `requestTimeout` を調整できます。`connectionTimeout` は、クライアントが接続を試みる際の最長待機時間 (ミリ秒単位) です。この時間内に確立できない場合は、接続を断念します。

`requestTimeout` では、リクエストが送信されてからクライアントがレスポンスを待機する時間 (ミリ秒単位) を定義します。いずれもデフォルト値は 0 です。その場合、タイムアウトは無効になり、レスポンスが届かなければクライアントは制限なく待ち続けることになります。ネットワークに問題が発生した場合にリクエストがエラーになり、新しいリクエストを開始できるように、妥当なタイムアウト値を設定しておいた方が賢明です。例えば、次のようになります。

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { NodeHttpHandler } from "@smithy/node-http-handler";

const requestHandler = new NodeHttpHandler({
  connectionTimeout: 2000,
  requestTimeout: 2000,
});

const client = new DynamoDBClient({
  requestHandler
});
```

**注記**  
この例では [Smithy](https://smithy.io/2.0/index.html) をインポートしています。Smithy はサービスと SDK を定義するための言語で、AWS が管理し、オープンソースで公開しています。

タイムアウト値を設定するほかに、最大ソケット数を設定し、オリジンあたりの同時接続数を増やすことができます。デベロッパーガイドでは、[`maxSockets` パラメータの設定](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html)について詳しく解説しています。

### キープアライブの設定
<a name="programming-with-javascript-config-keep-alive"></a>

HTTPS を使用する場合、最初のリクエストでは、安全な接続を確立するために何往復かの通信が必要になります。HTTP キープアライブを使用すると、すでに確立された接続を後続のリクエストで再利用できるため、リクエストの効率が上がり、レイテンシーが短縮されます。JavaScript V3 では、HTTP キープアライブがデフォルトで有効になっています。

アイドル状態の接続を維持できる時間には制限があります。接続がアイドル状態になるが、すでに確立されている接続を次のリクエストで利用したい場合は、定期的に (たとえば 1 分ごとに) リクエストを送信することを検討してください。

**注記**  
SDK の旧バージョン V2 では、キープアライブはデフォルトで無効になっているため、各接続は使用後すぐに切断されます。V2 を使用している場合は、この設定をオーバーライドできます。

### 再試行の設定
<a name="programming-with-javascript-config-retries"></a>

SDK がエラーレスポンスを受信し、そのエラーを SDK が再開可能であると判断した場合 (スロットリング例外や一時的なサービス例外など)、再試行されます。呼び出し側にはわからない形で行われますが、リクエスト成功までの時間が長引くという症状は現れます。

SDK for JavaScript V3 は、デフォルトではリクエストを合計 3 回行います。それで成功しなければそれ以上は再試行せず、呼び出し側のコンテキストにエラーを渡します。こうした再試行の回数と頻度を調整できます。

`DynamoDBClient` コンストラクタには、試行回数を制限する `maxAttempts` を設定できます。以下の例では、その値がデフォルトの 3 から合計 5 に引き上げられています。0 または 1 に設定した場合、自動再試行は不要であり、再開可能なエラーはキャッチブロック内で手動で処理するという意味になります。

```
const client = new DynamoDBClient({
  maxAttempts: 5,
});
```

また、再試行のタイミングも、カスタムの再試行戦略で制御できます。その場合は、`util-retry` ユーティリティパッケージをインポートし、現在の再試行が何回目かに応じて再試行の間隔を計算するカスタムのバックオフ関数を作成します。

以下の例では、1 回目の試行が失敗した場合は、15、30、90、360 ミリ秒と徐々に遅延を増やしながら最大 5 回試行するように指定しています。カスタムのバックオフ関数 ` calculateRetryBackoff` は、再試行回数 (初回の再試行が 1 で、以降増分) に応じて遅延を計算し、該当するリクエストで待機するミリ秒数を返します。

```
const { ConfiguredRetryStrategy } = require("@aws-sdk/util-retry");

const calculateRetryBackoff = (attempt) => {
  const backoffTimes = [15, 30, 90, 360];
  return backoffTimes[attempt - 1] || 0;
};

const client = new DynamoDBClient({
  retryStrategy: new ConfiguredRetryStrategy(
    5, // max attempts.
    calculateRetryBackoff // backoff function.
  ),
});
```

## ウェイター
<a name="programming-with-javascript-waiters"></a>

DynamoDB クライアントには、便利な[ウェーター関数](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/dynamodb/wait/index.html#cli-aws-dynamodb-wait)が 2 つあります。テーブルの作成、変更、削除時に、テーブルの変更が完了するまでコードの処理を待機させたい場合に、これらの関数を使用できます。例えば、テーブルをデプロイして `waitUntilTableExists` 関数を呼び出すと、テーブルが **ACTIVE** になるまでコードがブロックされます。ウェーターは内部的に 20 秒ごとに `describe-table` を実行し、DynamoDB サービスをポーリングします。

```
import {waitUntilTableExists, waitUntilTableNotExists} from "@aws-sdk/client-dynamodb";

… <create table details>

const results = await waitUntilTableExists({client: client, maxWaitTime: 180}, {TableName: "products"});
if (results.state == 'SUCCESS') {
  return results.reason.Table
}
console.error(`${results.state} ${results.reason}`);
```

`waitUntilTableExists` 関数は、`describe-table` コマンドを実行でき、テーブルのステータスが **ACTIVE** と表示された場合にのみ制御を返します。そのため、`waitUntilTableExists` を使用して、テーブルの作成や、GSI インデックスの追加などの変更の完了を待つことができます。こうした変更には時間がかかり、終わってからテーブルが **ACTIVE** ステータスに戻ります。

## エラー処理
<a name="programming-with-javascript-error-handling"></a>

ここで最初に紹介した数例では、すべてのエラーを網羅してキャッチしています。しかし、実際のアプリケーションでは、さまざまなエラータイプを見分け、より緻密なエラー処理を実装することが重要です。

DynamoDB エラーレスポンスには、エラーの名前を含むメタデータが含まれています。エラーをキャッチし、エラー条件の文字列名候補と照合して、処理方法を決定できます。サーバー側のエラーについては、`@aws-sdk/client-dynamodb` パッケージによってエクスポートされたエラータイプで `instanceof` 演算子を利用して、エラー処理を効率的に管理できます。

こうしたエラーは、再試行回数をすべて使い切って初めて露呈する点に注意が重要です。エラーが再試行され、最終的に呼び出しが成功した場合、コードの観点ではエラーは発生せず、レイテンシーが若干長引いただけになります。再試行は、スロットルリクエストやエラーリクエストなど、失敗したリクエストとして Amazon CloudWatch のグラフに表示されます。クライアントは再試行回数が最大回数に達すると、例外を生成します。つまり、クライアントはそれ以上再試行しないということがわかります。

以下のスニペットは、エラーをキャッチし、返されたエラーのタイプに基づいてアクションを実行します。

```
import {
  ResourceNotFoundException
  ProvisionedThroughputExceededException,
  DynamoDBServiceException,
} from "@aws-sdk/client-dynamodb";

try {
  await client.send(someCommand);
} catch (e) {
    if (e instanceof ResourceNotFoundException) {
      // Handle ResourceNotFoundException
    } else if (e instanceof ProvisionedThroughputExceededException) {
      // Handle ProvisionedThroughputExceededException
    } else if (e instanceof DynamoDBServiceException) {
      // Handle DynamoDBServiceException
    } else {
      // Other errors such as those from the SDK
      if (e.name === "TimeoutError") {
        // Handle SDK TimeoutError.
      } else {
        // Handle other errors.
      }
    }
}
```

一般的なエラー文字列については、「DynamoDB デベロッパーガイド**」の「[DynamoDB でのエラー処理](Programming.Errors.md)」を参照してください。特定の API コールで発生する可能性のある具体的なエラーについては、[Query API のドキュメント](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html)など、該当する API コールのドキュメントに記載されています。

エラーのメタデータには、エラーによって異なりますが、追加のプロパティが含まれます。` TimeoutError` の場合、以下に示すように、試行回数と `totalRetryDelay` がメタデータに含まれます。

```
{
  "name": "TimeoutError",
  "$metadata": {
    "attempts": 3,
    "totalRetryDelay": 199
  }
}
```

独自の再試行ポリシーを管理する場合は、スロットルとエラーを区別しておきましょう。
+ **スロットル** (` ProvisionedThroughputExceededException` または `ThrottlingException` で示される) は、DynamoDB テーブルまたはパーティションの読み取り容量または書き込み容量を超過したことを通知する正常なサービスを示します。1 ミリ秒が経過するごとに、読み取りまたは書き込みの容量が少しずつ増えるため、すぐに (50 ミリ秒ごとなど) 再試行して、新しく解放された容量へのアクセスを試みることができます。

   スロットルについては、エクスポネンシャルバックオフは特に必要ありません。軽量で DynamoDB が返しやすく、リクエストごとの課金も発生しないためです。エクスポネンシャルバックオフでは、すでに最長の待機時間が過ぎたクライアントスレッドの遅延をさらに長くしていくため、統計的に p50 と p99 が外側に広がります。
+ **エラー** (` InternalServerError` や `ServiceUnavailable` などで示される) が発生した場合は、サービス (テーブル全体、または読み取り/書き込み先のパーティションなど) に一時的な問題があります。エラーについては、再試行する前に比較的長く (250 ミリ秒や 500 ミリ秒など) 一時停止したり、ジッターを追加して再試行をずらしたりできます。

## ログ記録
<a name="programming-with-javascript-logging"></a>

ログ記録を有効にすると、SDK による処理内容を詳しく把握できます。以下の例に示すように、`DynamoDBClient` にパラメータを設定できます。ステータスコードや消費容量などのメタデータを含む詳細なログ情報がコンソールに表示されます。コードをターミナルウィンドウでローカルに実行した場合は、そのウィンドウにログが表示されます。AWS Lambda でコードを実行した場合、Amazon CloudWatch Logs が設定されていれば、コンソール出力がそのログに書き込まれます。

```
const client = new DynamoDBClient({
  logger: console
});
```

また、内部 SDK アクティビティにフックして、特定のイベントが発生したときにカスタムのログ記録を実行することもできます。以下の例では、クライアントの `middlewareStack` を使用して、各リクエストを SDK から送信された時点でインターセプトし、発生時にログに記録します。

```
const client = new DynamoDBClient({});

client.middlewareStack.add(
  (next) => async (args) => {
    console.log("Sending request from AWS SDK", { request: args.request });
    return next(args);
  },
  {
    step: "build",
    name: "log-ddb-calls",
  }
);
```

`MiddlewareStack` は、SDK の動作を観察して制御するための強力なフックを提供します。詳細については、ブログ「[Introducing Middleware Stack in Modular AWS SDK for JavaScript](https://aws.amazon.com/blogs/developer/middleware-stack-modular-aws-sdk-js/)」を参照してください。

## 考慮事項
<a name="programming-with-javascript-considerations"></a>

プロジェクトに AWS SDK for JavaScript を実装する際には、さらに以下の点を考慮する必要があります。

**モジュールシステム**  
SDK は CommonJS と ES (ECMAScript) の 2 つのモジュールシステムに対応しています。CommonJS は `require` 関数を使用し、ES は `import` キーワードを使用します。  

1. **CommonJS** – `const { DynamoDBClient, PutItemCommand } = require("@aws-sdk/client-dynamodb");`

1. **ES (ECMAScript** – `import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";`
プロジェクトタイプは package.json ファイルの type セクションで指定され、使用するモジュールシステムを決定します。デフォルトは CommonJS です。`"type": "module"` を使用して、ES プロジェクトを指定します。CommonJS パッケージ形式を使用する既存の Node.JS プロジェクトがある場合でも、関数ファイルに .mjs 拡張子の付いた名前を指定することで、より新しい SDK V3 Import 構文を使用して関数を追加できます。そうすることで、コードファイルを ES (ECMAScript) として扱うことができます。

**非同期オペレーション**  
コールバックとプロミスを使用して DynamoDB オペレーションの結果を処理するサンプルコードが多数あります。最近の JavaScript では、そのように複雑な処理は必要なく、デベロッパーはもっと簡潔で読みやすい async/await 構文を活用して非同期オペレーションを実行できます。

**ウェブブラウザランタイム**  
React または React Native を使用してビルドしているウェブ開発者やモバイル開発者は、各自のプロジェクトで SDK for JavaScript を使用できます。SDK の旧バージョン V2 では、ウェブ開発者は https://sdk.amazonaws.com/js/ でホストされている SDK イメージを参照して、SDK 全体をブラウザにロードする必要がありました。  
V3 では、必要な V3 クライアントモジュールと必要なすべての JavaScript 関数を Webpack を使用して単一の JavaScript ファイルにバンドルし、HTML ページの `<head>` のスクリプトタグに追加できます。詳しくは、SDK ドキュメントの「[Getting started in a browser script](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started-browser.html)」セクションで説明しています。

**DAX データプレーンオペレーション**  
Amazon DynamoDB Streams Accelerator (DAX) データプレーンオペレーションは、SDK for JavaScript V3 でサポートされています。

# AWS SDK for Java 2.x を使用した DynamoDB のプログラミング
<a name="ProgrammingWithJava"></a>

このプログラミングガイドは、Java で Amazon DynamoDB を使用することを検討しているプログラマーを対象としています。このガイドでは、抽象化レイヤー、設定管理、エラー処理、再試行ポリシーの制御、キープアライブの管理など、さまざまな概念について説明します。

**Topics**
+ [

## AWS SDK for Java 2.x について
](#AboutProgrammingWithJavaSDK)
+ [ご利用開始にあたって](#GetStartedProgrammingWithJavaSDK)
+ [SDK for Java 2.x ドキュメント](#ProgrammingWithJavaUseDoc)
+ [

## サポートされているインターフェイス
](#JavaInterfaces)
+ [

## その他のコード例
](#AdditionalCodeEx)
+ [同期プログラミングと非同期プログラミング](#SyncAsyncProgramming)
+ [

## HTTP クライアント
](#HttpClients)
+ [構成](#ConfigHttpClient)
+ [

## エラー処理
](#JavaErrorHandling)
+ [

## AWS リクエスト ID
](#JavaRequestID)
+ [

## ログ記録
](#JavaLogging)
+ [

## Pagination (ページ分割)
](#JavaPagination)
+ [

## データクラス注釈
](#JavaDataClassAnnotation)

## AWS SDK for Java 2.x について
<a name="AboutProgrammingWithJavaSDK"></a>

DynamoDB には、公式の AWS SDK for Java を使用して Java からアクセスできます。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/)されました。1.x は、2024 年 7 月 31 日にメンテナンスモードとなり、サポートは 2025 年 12 月 31 日に終了する予定です。新規開発には、2018 年に最初にリリースされた 2.x を使用することを強くお勧めします。このガイドは 2.x のみを対象としており、SDK の DynamoDB との関連性がある部分のみを重点的に取り扱っています。

AWS SDK のメンテナンスとサポートの詳細については、「**AWS SDKs and Tools Reference Guide」の「[AWS SDK and Tools maintenance policy](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html)」 および 「[AWS SDKs and Tools version support matrix](https://docs.aws.amazon.com/sdkref/latest/guide/version-support-matrix.html)」を参照してください。

AWS SDK for Java 2.x は、1.x コードベースより大幅に変更されています。SDK for Java 2.x は、Java 8 で導入されたノンブロッキング I/O などの最新の Java 機能をサポートしています。また、SDK for Java 2.x では、ネットワーク接続の柔軟性と構成可能性を高めるために、プラガブル HTTP クライアント実装のサポートも追加されています。

SDK for Java 1.x から SDK for Java 2.x への主な変更点は、パッケージ名の変更です。Java 1.x SDK は、`com.amazonaws` のパッケージ名を使用していますが、Java 2.x SDK は `software.amazon.awssdk` を使用します。同様に、Java 1.x SDK の Maven アーティファクトは `com.amazonaws` `groupId` を使用していますが、Java 2.x SDK のアーティファクトは `software.amazon.awssdk` `groupId` を使用します。

**重要**  
AWS SDK for Java 1.x には、`com.amazonaws.dynamodbv2` という名前の DynamoDB パッケージがあります。パッケージ名の「v2」は、Java 2 (J2SE) 用であることを示すものではありません。代わりに「v2」は、パッケージが低レベル API の[元のバージョン](Appendix.APIv20111205.md)ではなく、DynamoDB 低レベル API の [2 番目のバージョン](CurrentAPI.md)をサポートしていることを示します。

### Java バージョンのサポート
<a name="SupportedJavaVersions"></a>

AWS SDK for Java 2.x は、[Java リリース](https://github.com/aws/aws-sdk-java-v2?tab=readme-ov-file#maintenance-and-support-for-java-versions)の長期サポート (LTS) を完全にサポートします。

## AWS SDK for Java 2.x の開始方法
<a name="GetStartedProgrammingWithJavaSDK"></a>

次のチュートリアルでは、SDK for Java 2.x の依存関係を定義するために [Apache Maven](https://maven.apache.org/) を使用する方法を説明しています。このチュートリアルでは、DynamoDB に接続して使用可能な DynamoDB テーブルを一覧表示するコードの記述方法も説明します。このガイドのチュートリアルは、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Get started with the AWS SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html)」のチュートリアルに基づいています。このチュートリアルは、Amazon S3 の代わりに DynamoDB を呼び出すように編集されています。

**Topics**
+ [

### ステップ 1: このチュートリアルのために設定する
](#GetStartedJavaSetup)
+ [

### ステップ 2: プロジェクトを作成する
](#GetStartedJavaProjectSetup)
+ [

### ステップ 3: コードを記述する
](#GetStartedJavaCode)
+ [

### ステップ 4: アプリケーションをビルドして実行する
](#GetStartedRunJava)

### ステップ 1: このチュートリアルのために設定する
<a name="GetStartedJavaSetup"></a>

このチュートリアルを開始する前に、以下を実行する必要があります
+ DynamoDB へのアクセス許可。
+ AWS のサービス を使用して AWS アクセスポータル にアクセスするように設定された Java 開発環境。

このチュートリアル用にセットアップするには、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Setup overview](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup.html#setup-overview)」の手順に従う必要があります。Java SDK の[シングルサインオンアクセスを使用して開発環境を設定](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup.html#setup-credentials)し、[アクティブな AWS アクセスポータルセッション](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup.html#setup-login-sso)を確立した後、このチュートリアルの[ステップ 2](#GetStartedJavaProjectSetup) に進みます。

### ステップ 2: プロジェクトを作成する
<a name="GetStartedJavaProjectSetup"></a>

このチュートリアル用のプロジェクトを作成するには、プロジェクトの設定方法に関する入力を求める Maven コマンドを実行します。すべての入力を終えて確定すると、Maven は `pom.xml` ファイルとスタブ Java ファイルを作成して、プロジェクトの構築を完了します。

1. ターミナルまたはコマンドプロンプトウィンドウを開き、`Desktop` や `Home` フォルダなど、任意のディレクトリに移動します。

1. ターミナルに次のコマンドを入力して、**Enter** を押します。

   ```
   mvn archetype:generate \
      -DarchetypeGroupId=software.amazon.awssdk \
      -DarchetypeArtifactId=archetype-app-quickstart \
      -DarchetypeVersion=2.22.0
   ```

1. 各プロンプトで、2 列目に記載されている値を入力します。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/ProgrammingWithJava.html)

1. 最後の値を入力すると、Maven は選択した内容を一覧表示します。確認するには、**Y** と入力します。または、**N** と入力して値を再入力します。

Maven は、入力した `artifactId` 値に基づいて `getstarted` という名前が付けられたプロジェクトフォルダーを作成します。`getstarted` フォルダー内で、レビューできる `README.md` ファイル、`pom.xml` ファイル、および `src` ディレクトリを検索します。

Maven は以下のディレクトリーツリーを構築します。

```
getstarted
 ├── README.md
 ├── pom.xml
 └── src
     ├── main
     │   ├── java
     │   │   └── org
     │   │       └── example
     │   │           ├── App.java
     │   │           ├── DependencyFactory.java
     │   │           └── Handler.java
     │   └── resources
     │       └── simplelogger.properties
     └── test
         └── java
             └── org
                 └── example
                     └── HandlerTest.java
 
 10 directories, 7 files
```

以下は、`pom.xml` プロジェクトファイルの内容を示しています。

#### `pom.xml`
<a name="ProjectSetupCollapse2"></a>

`dependencyManagement` セクションには AWS SDK for Java 2.x への依存関係が含まれており、`dependencies` セクションには DynamoDB に対する依存関係があります。このような依存関係を指定すると、Maven は関連する `.jar` ファイルを Java クラスパスに強制的に含めます。デフォルトでは、AWS SDK にはすべての AWS のサービス クラスは含まれません。DynamoDB で低レベルインターフェイスを使用する場合、`dynamodb` アーティファクトへの依存関係が必要です。高レベルインターフェイスを使用する場合は、`dynamodb-enhanced` アーティファクトへの依存関係が必要です。関連する依存関係が含まれていない場合、コードはコンパイルされません。プロジェクトでは Java 1.8 が使用されています。これは、`maven.compiler.source`、`maven.compiler.target` およびプロパティに `1.8` 値があるためです。

```
<?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>org.example</groupId>
     <artifactId>getstarted</artifactId>
     <version>1.0-SNAPSHOT</version>
     <packaging>jar</packaging>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
         <maven.shade.plugin.version>3.2.1</maven.shade.plugin.version>
         <maven.compiler.plugin.version>3.6.1</maven.compiler.plugin.version>
         <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
         <aws.java.sdk.version>2.22.0</aws.java.sdk.version> <-------- SDK version picked up from archetype version.
         <slf4j.version>1.7.28</slf4j.version>
         <junit5.version>5.8.1</junit5.version>
     </properties>
 
     <dependencyManagement>
         <dependencies>
             <dependency>
                 <groupId>software.amazon.awssdk</groupId>
                 <artifactId>bom</artifactId>
                 <version>${aws.java.sdk.version}</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
         </dependencies>
     </dependencyManagement>
 
     <dependencies>
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>dynamodb</artifactId>  <-------- DynamoDB dependency
             <exclusions>
                 <exclusion>
                     <groupId>software.amazon.awssdk</groupId>
                     <artifactId>netty-nio-client</artifactId>
                 </exclusion>
                 <exclusion>
                     <groupId>software.amazon.awssdk</groupId>
                     <artifactId>apache-client</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
 
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>sso</artifactId> <-------- Required for identity center authentication.
         </dependency>
 
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>ssooidc</artifactId> <-------- Required for identity center authentication.
         </dependency>
 
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>apache-client</artifactId> <-------- HTTP client specified.
             <exclusions>
                 <exclusion>
                     <groupId>commons-logging</groupId>
                     <artifactId>commons-logging</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
 
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
             <version>${slf4j.version}</version>
         </dependency>
 
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-simple</artifactId>
             <version>${slf4j.version}</version>
         </dependency>
 
         <!-- Needed to adapt Apache Commons Logging used by Apache HTTP Client to Slf4j to avoid
         ClassNotFoundException: org.apache.commons.logging.impl.LogFactoryImpl during runtime -->
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>jcl-over-slf4j</artifactId>
             <version>${slf4j.version}</version>
         </dependency>
 
         <!-- Test Dependencies -->
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter</artifactId>
             <version>${junit5.version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
 
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <version>${maven.compiler.plugin.version}</version>
             </plugin>
         </plugins>
     </build>
 
 </project>
```

### ステップ 3: コードを記述する
<a name="GetStartedJavaCode"></a>

次のコードは Maven によって作成された `App` クラスを示しています。`main` メソッドはアプリケーションへのエントリポイントであり、`Handler` クラスのインスタンスを作成してその `sendRequest` メソッドを呼び出します。

#### `App` クラス
<a name="projectsetup-collapse2"></a>

```
package org.example;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class App {
     private static final Logger logger = LoggerFactory.getLogger(App.class);
 
     public static void main(String... args) {
         logger.info("Application starts");
 
         Handler handler = new Handler();
         handler.sendRequest();
 
         logger.info("Application ends");
     }
 }
```

Maven が作成する `DependencyFactory` クラスには、[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html) インスタンスを構築して返す `dynamoDbClient` ファクトリメソッドが含まれています。`DynamoDbClient` インスタンスは Apache ベースの HTTP クライアントのインスタンスを使用します。これは、どの HTTP クライアントを使用するかを Maven が求めたときに `apache-client` が指定されたためです。

次のコードは `DependencyFactory` クラスを示しています。

#### DependencyFactory クラス
<a name="code-collapse2"></a>

```
package org.example;
 
 import software.amazon.awssdk.http.apache.ApacheHttpClient;
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 
 /**
  * The module containing all dependencies required by the {@link Handler}.
  */
 public class DependencyFactory {
 
     private DependencyFactory() {}
 
     /**
      * @return an instance of DynamoDbClient
      */
     public static DynamoDbClient dynamoDbClient() {
         return DynamoDbClient.builder()
                        .httpClientBuilder(ApacheHttpClient.builder())
                        .build();
     }
 }
```

`Handler` クラスにはプログラムのメインロジックが含まれています。`Handler` のインスタンスが `App` クラス内で作成されると、`DependencyFactory` は `DynamoDbClient` サービスクライアントを配置します。コードでは、`DynamoDbClient` インスタンスを使用して DynamoDB を呼び出します。

Maven は `TODO` コメント付きの次の `Handler` クラスを生成します。チュートリアルの次のステップでは、*`TODO`* コメントをコードに置き換えます。

#### Maven によって生成された `Handler` クラス
<a name="code-collapsible3"></a>

```
package org.example;
 
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 
 
 public class Handler {
     private final DynamoDbClient dynamoDbClient;
 
     public Handler() {
         dynamoDbClient = DependencyFactory.dynamoDbClient();
     }
 
     public void sendRequest() {
         // TODO: invoking the API calls using dynamoDbClient.
     }
 }
```

ロジックを設定するには、`Handler` クラスのすべてのコンテンツを次のコードに置き換えます。`sendRequest` メソッドが入力され、必要なインポートが追加されます。

#### `Handler` クラス、実装済み
<a name="code-collapse4"></a>

次のコードでは、[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)インスタンスを使用して既存のテーブルのリストを取得します。特定のアカウントと AWS リージョン にテーブルが配置されている場合、コードは `Logger` インスタンスを使用してこのようなテーブルの名前をログ記録します。

```
package org.example;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;
 
 
 public class Handler {
     private final DynamoDbClient dynamoDbClient;
 
     public Handler() {
         dynamoDbClient = DependencyFactory.dynamoDbClient();
     }
 
     public void sendRequest() {
         Logger logger = LoggerFactory.getLogger(Handler.class);
 
         logger.info("calling the DynamoDB API to get a list of existing tables");
         ListTablesResponse response = dynamoDbClient.listTables();
 
         if (!response.hasTableNames()) {
             logger.info("No existing tables found for the configured account & region");
         } else {
             response.tableNames().forEach(tableName -> logger.info("Table: " + tableName));
         }
     }
 }
```

### ステップ 4: アプリケーションをビルドして実行する
<a name="GetStartedRunJava"></a>

プロジェクトが作成され、完全な `Handler` クラスを含めたら、アプリケーションを構築して実行します。

1. アクティブな AWS IAM アイデンティティセンター セッションがあることを確認します。確認するには、AWS Command Line Interface (AWS CLI) コマンド `aws sts get-caller-identity` を実行してレスポンスを確認します。アクティブなセッションがない場合は、「[Sign in using the AWS CLI](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup.html#setup-login-sso)」の手順を参照してください。

1. ターミナルまたはコマンドプロンプトウィンドウを開いて、プロジェクトディレクトリ `getstarted` に移動します。

1. 次のコマンドを使用して、プロジェクトを構築します。

   ```
   mvn clean package
   ```

1. 次のコマンドを使用して、アプリケーションを実行します。

   ```
   mvn exec:java -Dexec.mainClass="org.example.App"
   ```

ファイルを表示した後、オブジェクトを削除し、その後にバケットを削除します。

#### Success
<a name="GetStartedSuccessJava"></a>

Maven プロジェクトがエラーなしで構築および実行された場合は、正常に完了しています\$1 これで、Java 2.x 用 SDK を使用して最初の Java アプリケーションを正常に構築できました。

#### クリーンアップ
<a name="GetStartedCleanupJava"></a>

このチュートリアルで作成したリソースをクリーンアップするには、プロジェクトフォルダ `getstarted` を削除します。

## AWS SDK for Java 2.x ドキュメントのレビュー
<a name="ProgrammingWithJavaUseDoc"></a>

「[https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html)AWS SDK for Java 2.x デベロッパーガイド」は、すべての AWS のサービス サービスにおける SDK のすべての側面について説明しています。以下のトピックを確認することをお勧めします。
+ [Migrate from version 1.x to 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html) — 1.x と 2.x の違いについて詳細に説明しています。このトピックでは、両方のメジャーバージョンを並行して使用する方法も説明しています。
+ [DynamoDB guide for Java 2.x SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/examples-dynamodb.html) — テーブルの作成、項目の操作、項目の取得など、基本的な DynamoDB のオペレーションを実行する方法を説明しています。上記の例では、低レベルインターフェイスを使用しています。「[サポートされているインターフェイス](#JavaInterfaces)」セクションで説明するとおり、Java には複数のインターフェイスがあります。

**ヒント**  
これらのトピックを確認したら、「[AWS SDK for Java 2.x API Reference](https://sdk.amazonaws.com/java/api/latest/)」をブックマークします。このガイドはすべての AWS のサービス を対象としており、主な API リファレンスとして使用することをお勧めします。

## サポートされているインターフェイス
<a name="JavaInterfaces"></a>

AWS SDK for Java 2.x は、必要な抽象化レベルに応じて、以下のインターフェイスをサポートします。

**Topics**
+ [

### 低レベルインターフェイス
](#LowLevelInterface)
+ [

### 高レベルインターフェイス
](#HighLevelInterface)
+ [

### Document インターフェイス
](#DocumentInterface)
+ [

### `Query` 例を使用したインターフェイスの比較
](#CompareJavaInterfacesQueryEx)

### 低レベルインターフェイス
<a name="LowLevelInterface"></a>

低レベルインターフェイスは、基盤となるサービス API に 1 対 1 でマッピングされています。すべての DynamoDB API は、このインターフェイスを介して利用できます。つまり、低レベルのインターフェイスでは完全な機能を提供するものの、多くの場合、使い方はより冗長で複雑になります。例えば、文字列を保持するには `.s()` 関数を使用し、数値を保持するには `.n()` 関数を使用する必要があります。次の [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) の例では、低レベルインターフェイスを使用して項目を挿入しています。

```
import org.slf4j.*;
import software.amazon.awssdk.http.crt.AwsCrtHttpClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.*;

import java.util.Map;

public class PutItem {

    // Create a DynamoDB client with the default settings connected to the DynamoDB
    // endpoint in the default region based on the default credentials provider chain.
    private static final DynamoDbClient DYNAMODB_CLIENT = DynamoDbClient.create();
    private static final Logger LOGGER = LoggerFactory.getLogger(PutItem.class);

    private void putItem() {
        PutItemResponse response = DYNAMODB_CLIENT.putItem(PutItemRequest.builder()
                .item(Map.of(
                        "pk", AttributeValue.builder().s("123").build(),
                        "sk", AttributeValue.builder().s("cart#123").build(),
                        "item_data", AttributeValue.builder().s("YourItemData").build(),
                        "inventory", AttributeValue.builder().n("500").build()
                        // ... more attributes ...
                ))
                .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)
                .tableName("YourTableName")
                .build());
        LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)");
    }
}
```

### 高レベルインターフェイス
<a name="HighLevelInterface"></a>

AWS SDK for Java 2.x の高レベルインターフェイスは DynamoDB 拡張クライアントと呼ばれます。このインターフェイスでは、より慣用的なコード作成エクスペリエンスが提供されます。

拡張クライアントでは、クライアント側のデータクラスと、そのデータを保存するように設計された複数の DynamoDB テーブル間でマッピングできます。テーブルおよび対応するモデルクラスの間の関係をコードで定義します。これにより、SDK を利用してデータ型の操作を管理できます。拡張クライアントの詳細については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[DynamoDB enhanced client API](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)」を参照してください。

次の [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) の例では、高レベルインターフェイスを使用してしています。この例では、`YourItem` という名前の `DynamoDbBean` が `TableSchema` を作成して、`putItem()` 呼び出しの入力として直接使用できるようにしています。

```
import org.slf4j.*;
import software.amazon.awssdk.enhanced.dynamodb.*;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*;
import software.amazon.awssdk.enhanced.dynamodb.model.*;
import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity;

public class DynamoDbEnhancedClientPutItem {
    private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build();
    private static final DynamoDbTable<YourItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromBean(YourItem.class));
    private static final Logger LOGGER = LoggerFactory.getLogger(PutItem.class);

    private void putItem() {
        PutItemEnhancedResponse<YourItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourItem.class)
                .item(new YourItem("123", "cart#123", "YourItemData", 500))
                .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)
                .build());
        LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)");
    }

    @DynamoDbBean
    public static class YourItem {

        public YourItem() {}

        public YourItem(String pk, String sk, String itemData, int inventory) {
            this.pk = pk;
            this.sk = sk;
            this.itemData = itemData;
            this.inventory = inventory;
        }

        private String pk;
        private String sk;
        private String itemData;

        private int inventory;

        @DynamoDbPartitionKey
        public void setPk(String pk) {
            this.pk = pk;
        }

        public String getPk() {
            return pk;
        }

        @DynamoDbSortKey
        public void setSk(String sk) {
            this.sk = sk;
        }

        public String getSk() {
            return sk;
        }

        public void setItemData(String itemData) {
            this.itemData = itemData;
        }

        public String getItemData() {
            return itemData;
        }

        public void setInventory(int inventory) {
            this.inventory = inventory;
        }

        public int getInventory() {
            return inventory;
        }
    }
}
```

AWS SDK for Java 1.x には独自の高レベルインターフェイスがあり、メインクラス `DynamoDBMapper` で頻繁に参照されます。AWS SDK for Java 2.x は `software.amazon.awssdk.enhanced.dynamodb` という名前の別のパッケージ (と Maven アーティファクト) で公開されています。Java 2.x SDK は、メインクラス `DynamoDbEnhancedClient` で頻繁に参照されます。

#### イミュータブルデータクラスを使用する高レベルインターフェイス
<a name="HighLevelInterfaceImmutableDataClasses"></a>

DynamoDB 拡張クライアント API のマッピング機能は、イミュータブルデータクラスで動作します。不変クラスにはゲッターしかなく、SDK がクラスのインスタンスを作成するために使用するビルダークラスが必要です。Java のイミュータブルクラスは、開発者が副作用のないクラスを作成するために使用できる一般的なスタイルです。これらのクラスの動作は、複雑なマルチスレッドアプリケーションでより予測可能になります。「[High-level interface example](#highleveleg)」で説明したとおり、`@DynamoDbBean` アノテーションを使用する代わりに、イミュータブルクラスは Builder クラスを入力として受け取る `@DynamoDbImmutable` アノテーションを使用します。

次の例では、`DynamoDbEnhancedClientImmutablePutItem` Builder クラスを入力としてテーブルスキーマを作成します。この例では次に、スキーマを [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) API コールの入力として使用します。

```
import org.slf4j.*;
import software.amazon.awssdk.enhanced.dynamodb.*;
import software.amazon.awssdk.enhanced.dynamodb.model.*;
import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity;

public class DynamoDbEnhancedClientImmutablePutItem {
    private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build();
    private static final DynamoDbTable<YourImmutableItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromImmutableClass(YourImmutableItem.class));
    private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientImmutablePutItem.class);

    private void putItem() {
        PutItemEnhancedResponse<YourImmutableItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourImmutableItem.class)
                .item(YourImmutableItem.builder()
                                        .pk("123")
                                        .sk("cart#123")
                                        .itemData("YourItemData")
                                        .inventory(500)
                                        .build())
                .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)
                .build());
        LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)");
    }
}
```

次の例は、イミュータブルデータクラスを示しています。

```
@DynamoDbImmutable(builder = YourImmutableItem.YourImmutableItemBuilder.class)
class YourImmutableItem {
    private final String pk;
    private final String sk;
    private final String itemData;
    private final int inventory;
    public YourImmutableItem(YourImmutableItemBuilder builder) {
        this.pk = builder.pk;
        this.sk = builder.sk;
        this.itemData = builder.itemData;
        this.inventory = builder.inventory;
    }

    public static YourImmutableItemBuilder builder() { return new YourImmutableItemBuilder(); }

    @DynamoDbPartitionKey
    public String getPk() {
        return pk;
    }

    @DynamoDbSortKey
    public String getSk() {
        return sk;
    }

    public String getItemData() {
        return itemData;
    }

    public int getInventory() {
        return inventory;
    }

    static final class YourImmutableItemBuilder {
        private String pk;
        private String sk;
        private String itemData;
        private int inventory;

        private YourImmutableItemBuilder() {}

        public YourImmutableItemBuilder pk(String pk) { this.pk = pk; return this; }
        public YourImmutableItemBuilder sk(String sk) { this.sk = sk; return this; }
        public YourImmutableItemBuilder itemData(String itemData) { this.itemData = itemData; return this; }
        public YourImmutableItemBuilder inventory(int inventory) { this.inventory = inventory; return this; }

        public YourImmutableItem build() { return new YourImmutableItem(this); }
    }
}
```

#### イミュータブルデータクラスとサードパーティーのボイラープレート生成ライブラリを使用する高レベルインターフェイス
<a name="ImmutableDataClassesThirdPartyBoilerplateGenLib"></a>

前のセクションで説明したイミュータブルデータクラスの例では、いくつかのボイラープレートコードが必要です。例えば、`Builder` クラス以外にも、データクラスには getter ロジックと setter ロジックがあります。[Project Lombok](https://projectlombok.org/) などのサードパーティーライブラリは、このようなタイプのボイラープレートコードの生成に役立ちます。ボイラープレートコードの大部分を低減すると、イミュータブルデータクラスと AWS SDK の使用に必要なコードの量を制限できます。これにより、コードの生産性と可読性がさらに向上します。詳細については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Use third-party libraries, such as Lombok](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-use-immut.html#ddb-en-client-use-immut-lombok)」を参照してください。

次の例は、Project Lombok が DynamoDB 拡張クライアント API を使用するために必要なコードをどのように簡略化できるかを示しています。

```
import org.slf4j.*;
import software.amazon.awssdk.enhanced.dynamodb.*;
import software.amazon.awssdk.enhanced.dynamodb.model.*;
import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity;

public class DynamoDbEnhancedClientImmutableLombokPutItem {

    private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build();
    private static final DynamoDbTable<YourImmutableLombokItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromImmutableClass(YourImmutableLombokItem.class));
    private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientImmutableLombokPutItem.class);

    private void putItem() {
        PutItemEnhancedResponse<YourImmutableLombokItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourImmutableLombokItem.class)
                .item(YourImmutableLombokItem.builder()
                        .pk("123")
                        .sk("cart#123")
                        .itemData("YourItemData")
                        .inventory(500)
                        .build())
                .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)
                .build());
        LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)");
    }
}
```

次の例は、イミュータブルデータクラスのイミュータブルデータオブジェクトを示しています。

```
import lombok.*;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*;

@Builder
@DynamoDbImmutable(builder = YourImmutableLombokItem.YourImmutableLombokItemBuilder.class)
@Value
public class YourImmutableLombokItem {

    @Getter(onMethod_=@DynamoDbPartitionKey)
    String pk;
    @Getter(onMethod_=@DynamoDbSortKey)
    String sk;
    String itemData;
    int inventory;
}
```

`YourImmutableLombokItem` クラスは Project Lombok と AWS SDK が提供する以下のアノテーションを使用します。
+ [@Builder](https://projectlombok.org/features/Builder) — Project Lombok が提供するデータクラス用の複雑な Builder API を生成します。
+ [@DynamoDbImmutable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbImmutable.html) — `DynamoDbImmutable` クラスを、AWS SDK が提供する DynamoDB マッピング可能なエンティティのアノテーションとして識別します。
+ [@Value](https://projectlombok.org/features/Value) – `@Data` のイミュータブルバリアント。デフォルトで、すべてのフィールドはプライベートかつ最終的なものになり、setters は生成されません。Project Lombok はこのアノテーションを提供します。

### Document インターフェイス
<a name="DocumentInterface"></a>

AWS SDK for Java 2.x Document インターフェイスでは、データ型記述子を指定する必要がありません。データ型は、データ自体のセマンティクスによって暗示されています。この Document インターフェイスは AWS SDK for Java 1.x の Document インターフェイスに似ていますが、インターフェイスは再設計されています。

次の [Document interface example](#DocInterfaceEg) は、この Document インターフェイスを使用した `PutItem` コールの表現を示しています。この例では EnhancedDocument も使用しています。Enhanced Document API を使用して DynamoDB テーブルに対してコマンドを実行するには、まずテーブルを Document テーブルスキーマに関連付けて、`DynamoDBTable` リソースオブジェクトを作成する必要があります。Document テーブルスキーマの Builder には、プライマリインデックスキーと属性コンバーターのプロバイダーが必要です。

デフォルトタイプの Document 属性の変換には `AttributeConverterProvider.defaultProvider()` を使用できます。全体的なデフォルト動作は、カスタム `AttributeConverterProvider` 実装で変更できます。また、1 つの属性のコンバーターを変更することもできます。「[AWS SDK および ツールリファレンスガイド](https://docs.aws.amazon.com/sdkref/latest/guide/version-support-matrix.html)」には、カスタムコンバーターの使用方法の詳細と例が提供されています。コンバーターは主に、デフォルトコンバーターがないドメインクラスの属性に使用します。カスタムコンバータを使用すると、DynamoDB への書き込みまたは読み取りに必要な情報を SDK に提供できます。

```
import org.slf4j.*;
import software.amazon.awssdk.enhanced.dynamodb.*;
import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument;
import software.amazon.awssdk.enhanced.dynamodb.model.*;
import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity;

public class DynamoDbEnhancedDocumentClientPutItem {
    private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build();
    private static final DynamoDbTable<EnhancedDocument> DYNAMODB_TABLE =
            ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.documentSchemaBuilder()
                            .addIndexPartitionKey(TableMetadata.primaryIndexName(),"pk", AttributeValueType.S)
                            .addIndexSortKey(TableMetadata.primaryIndexName(), "sk", AttributeValueType.S)
                            .attributeConverterProviders(AttributeConverterProvider.defaultProvider())
                            .build());

    private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedDocumentClientPutItem.class);

    private void putItem() {
        PutItemEnhancedResponse<EnhancedDocument> response = DYNAMODB_TABLE.putItemWithResponse(
                        PutItemEnhancedRequest.builder(EnhancedDocument.class)
                                .item(
                                    EnhancedDocument.builder()
                                            .attributeConverterProviders(AttributeConverterProvider.defaultProvider())
                                            .putString("pk", "123")
                                            .putString("sk", "cart#123")
                                            .putString("item_data", "YourItemData")
                                            .putNumber("inventory", 500)
                                            .build())
                                .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)
                                .build());
        LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)");
    }

}
```

JSON ドキュメントとネイティブの Amazon DynamoDB のデータ型との間の変換を行うには、以下のユーティリティメソッドを使用します。
+ [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html#fromJson(java.lang.String)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html#fromJson(java.lang.String)) — JSON 文字列から新しい EnhancedDocument インスタンスを作成します。
+ [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html#toJson()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html#toJson()) — Document の JSON 文字列表現を作成して、その他の JSON オブジェクトと同様にアプリケーションで使用できるようにします。

### `Query` 例を使用したインターフェイスの比較
<a name="CompareJavaInterfacesQueryEx"></a>

このセクションでは、さまざまなインターフェイスにおける、同じ [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) 呼び出しの表現について説明します。これらのクエリの結果を微調整する場合は、以下の点に注意してください。
+ DynamoDB では、単一の特定のパーティションキー値をターゲットにするため、パーティションキーは完全に指定する必要があります。
+ ソートキーには `begins_with` を使用したキー条件式があるため、カートの商品のみがこのクエリの対象となります。
+ 返される項目を最大 100 個に制限するために、クエリでは `limit()` を使用します。
+ `scanIndexForward` は false に設定します。結果は UTF-8 バイトの順序で返されます。つまり通常、番号が最も小さいカートの商品が最初に返されます。`scanIndexForward` を false に設定すると、この順序が逆になり、番号が最も大きいカートの商品が最初に返されます。
+ フィルターを適用して、条件に一致しない結果をすべて削除します。項目がフィルターに一致するかどうかにかかわらず、フィルターが適用されるデータは読み取りキャパシティを消費します。

**Example 低レベルインターフェイスを使用した `Query`**  
次の例では、`keyConditionExpression` を使用して、`YourTableName` という名前のテーブルをクエリします。これにより、特定のプレフィックス値で始まる特定のパーティションキー値とソートキー値にクエリが制限されます。このようなキーの条件は、DynamoDB から読み取られるデータ量を制限します。このクエリは最後に、`filterExpression` を使用して DynamoDB から取得したデータにフィルターを適用します。  

```
import org.slf4j.*;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.*;

import java.util.Map;

public class Query {

    // Create a DynamoDB client with the default settings connected to the DynamoDB 
    // endpoint in the default region based on the default credentials provider chain.
    private static final DynamoDbClient DYNAMODB_CLIENT = DynamoDbClient.builder().build();
    private static final Logger LOGGER = LoggerFactory.getLogger(Query.class);

    private static void query() {
        QueryResponse response = DYNAMODB_CLIENT.query(QueryRequest.builder()
                .expressionAttributeNames(Map.of("#name", "name"))
                .expressionAttributeValues(Map.of(
                    ":pk_val", AttributeValue.fromS("id#1"),
                    ":sk_val", AttributeValue.fromS("cart#"),
                    ":name_val", AttributeValue.fromS("SomeName")))
                .filterExpression("#name = :name_val")
                .keyConditionExpression("pk = :pk_val AND begins_with(sk, :sk_val)")
                .limit(100)
                .scanIndexForward(false)
                .tableName("YourTableName")
                .build());

        LOGGER.info("nr of items: " + response.count());
        LOGGER.info("First item pk: " + response.items().get(0).get("pk"));
        LOGGER.info("First item sk: " + response.items().get(0).get("sk"));
    }
}
```

**Example Document インターフェイスを使用した `Query`**  
次の例では、Document インターフェイスを使用して、`YourTableName` という名前のテーブルをクエリします。  

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.enhanced.dynamodb.*;
import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument;
import software.amazon.awssdk.enhanced.dynamodb.model.*;

import java.util.Map;

public class DynamoDbEnhancedDocumentClientQuery {

    // Create a DynamoDB client with the default settings connected to the DynamoDB 
    // endpoint in the default region based on the default credentials provider chain.
    private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build();
    private static final DynamoDbTable<EnhancedDocument> DYNAMODB_TABLE =
            ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.documentSchemaBuilder()
                    .addIndexPartitionKey(TableMetadata.primaryIndexName(),"pk", AttributeValueType.S)
                    .addIndexSortKey(TableMetadata.primaryIndexName(), "sk", AttributeValueType.S)
                    .attributeConverterProviders(AttributeConverterProvider.defaultProvider())
                    .build());
    private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedDocumentClientQuery.class);

    private void query() {
        PageIterable<EnhancedDocument> response = DYNAMODB_TABLE.query(QueryEnhancedRequest.builder()
                .filterExpression(Expression.builder()
                        .expression("#name = :name_val")
                        .expressionNames(Map.of("#name", "name"))
                        .expressionValues(Map.of(":name_val", AttributeValue.fromS("SomeName")))
                        .build())
                .limit(100)
                .queryConditional(QueryConditional.sortBeginsWith(Key.builder()
                        .partitionValue("id#1")
                        .sortValue("cart#")
                        .build()))
                .scanIndexForward(false)
                .build());

        LOGGER.info("nr of items: " + response.items().stream().count());
        LOGGER.info("First item pk: " + response.items().iterator().next().getString("pk"));
        LOGGER.info("First item sk: " + response.items().iterator().next().getString("sk"));

    }
}
```

**Example 高レベルインターフェイスを使用した `Query`**  
次の例では、DynamoDB Enhanced Client API を使用して、`YourTableName` という名前のテーブルをクエリします。  

```
import org.slf4j.*;
import software.amazon.awssdk.enhanced.dynamodb.*;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*;
import software.amazon.awssdk.enhanced.dynamodb.model.*;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

import java.util.Map;

public class DynamoDbEnhancedClientQuery {

    private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build();
    private static final DynamoDbTable<YourItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromBean(DynamoDbEnhancedClientQuery.YourItem.class));
    private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientQuery.class);

    private void query() {
        PageIterable<YourItem> response = DYNAMODB_TABLE.query(QueryEnhancedRequest.builder()
                .filterExpression(Expression.builder()
                        .expression("#name = :name_val")
                        .expressionNames(Map.of("#name", "name"))
                        .expressionValues(Map.of(":name_val", AttributeValue.fromS("SomeName")))
                        .build())
                .limit(100)
                .queryConditional(QueryConditional.sortBeginsWith(Key.builder()
                        .partitionValue("id#1")
                        .sortValue("cart#")
                        .build()))
                .scanIndexForward(false)
                .build());

        LOGGER.info("nr of items: " + response.items().stream().count());
        LOGGER.info("First item pk: " + response.items().iterator().next().getPk());
        LOGGER.info("First item sk: " + response.items().iterator().next().getSk());
    }

    @DynamoDbBean
    public static class YourItem {

        public YourItem() {}

        public YourItem(String pk, String sk, String name) {
            this.pk = pk;
            this.sk = sk;
            this.name = name;
        }

        private String pk;
        private String sk;
        private String name;

        @DynamoDbPartitionKey
        public void setPk(String pk) {
            this.pk = pk;
        }

        public String getPk() {
            return pk;
        }

        @DynamoDbSortKey
        public void setSk(String sk) {
            this.sk = sk;
        }

        public String getSk() {
            return sk;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}
```
**イミュータブルデータクラスを使用する高レベルインターフェイス**  
高レベルのイミュータブルデータクラスを使用して `Query` を実行する場合、`YourItem` または `YourImmutableItem` エンティティクラスの構築を除き、コードは高レベルインターフェイスの例と同じです。詳細については、「[PutItem](#HighLevelImmutableDataClassEg)」の例を参照してください。
**イミュータブルデータクラスとサードパーティーのボイラープレート生成ライブラリを使用する高レベルインターフェイス**  
高レベルのイミュータブルデータクラスを使用して `Query` を実行する場合、`YourItem` または `YourImmutableLombokItem` エンティティクラスの構築を除き、コードは高レベルインターフェイスの例と同じです。詳細については、「[PutItem](#HighLevelImmutableDataClassEg)」の例を参照してください。

## その他のコード例
<a name="AdditionalCodeEx"></a>

SDK for Java 2.x で DynamoDB を使用する場合のその他の例については、以下のコードサンプルリポジトリを参照してください。
+ [AWS 公式シングルアクションのコード例](https://docs.aws.amazon.com/code-library/latest/ug/java_2_dynamodb_code_examples.html)
+ [コミュニティが管理するシングルアクションのコード例](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/java)
+ [AWS 公式のシナリオ指向コード例](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/java)

## 同期プログラミングと非同期プログラミング
<a name="SyncAsyncProgramming"></a>

AWS SDK for Java 2.x は、DynamoDB などの AWS のサービス に**同期クライアントと**非同期クライアントの両方を提供します。

`DynamoDbClient` クラスと `DynamoDbEnhancedClient` クラスは、クライアントがサービスから応答を受信するまでスレッドの実行をブロックする同期メソッドを提供します。非同期のオペレーションが必要ない場合、このクライアントは DynamoDB を操作する最も簡単な方法です。

`DynamoDbAsyncClient` クラスと `DynamoDbEnhancedAsyncClient` クラスは、直ちに呼び出し元に戻り、応答を待たずに呼び出し元のスレッドに制御を返す非同期メソッドを提供します。ノンブロッキングクライアントの場合、少数のスレッド間で優れた同時実行が可能で、最小限のコンピューティングリソースで I/O リクエストを効率的に処理できるという利点があります。これにより、スループットと即応性が向上します。

AWS SDK for Java 2.x はノンブロッキング I/O のネイティブサポートを使用しています。AWS SDK for Java 1.x ではノンブロッキング I/O をシミュレートする必要がありました。

非同期メソッドは応答が利用できるようになる前に呼び出し元に戻るため、応答の準備ができたら応答を取得する手段を講じる必要があります。AWS SDK for Java の非同期メソッドは、その後の非同期オペレーションの結果を含む [https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/CompletableFuture.html](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/CompletableFuture.html) オブジェクトを返します。このような `CompletableFuture` オブジェクトに対して `get()` または `join()` を呼び出すと、結果が利用できるようになるまでコードはブロックされます。リクエストと同時にこれらの呼び出しを行う場合、動作は通常の同期呼び出しと同様になります。

非同期プログラミングの詳細については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Use asynchronous programming](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/asynchronous.html)」を参照してください。

## HTTP クライアント
<a name="HttpClients"></a>

すべてのクライアントをサポートするための AWS のサービス との通信を処理する HTTP クライアントがあります。アプリケーションに最も適切な特性を持つ HTTP クライアントを選択して、代替 HTTP クライアントをプラグインできます。比較的軽量なクライアントも、設定オプションが豊富にあるクライアントもあります。

HTTP クライアントによっては、同期使用のみをサポートするものもあれば、非同期使用のみをサポートするものもあります。ワークロードに最適な HTTP クライアントの選択に役立つフローチャートについては、「**AWS SDK for Java 2.x デベロッパーガイド」の「[HTTP client recommendations](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration.html#http-clients-recommend)」を参照してください。

利用できる HTTP クライアントのいくつかを次の一覧にまとめています。

**Topics**
+ [

### Apache ベースの HTTP クライアント
](#ApacheHttpClient)
+ [

### `URLConnection` ベースの HTTP クライアント
](#URLConnHttpClient)
+ [

### Netty ベースの HTTP クライアント
](#NettyHttpClient)
+ [

### AWS CRT ベースの HTTP クライアント
](#AWSCRTHttpClient)

### Apache ベースの HTTP クライアント
<a name="ApacheHttpClient"></a>

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache/ApacheHttpClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache/ApacheHttpClient.html) クラスは同期サービスクライアントをサポートします。これは同期でのデフォルトの HTTP クライアントです。`ApacheHttpClient` クラスの設定については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Configure the Apache-based HTTP client](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration-apache.html)」を参照してください。

### `URLConnection` ベースの HTTP クライアント
<a name="URLConnHttpClient"></a>

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html) クラスは、同期クライアント向けのもう 1 つのオプションです。Apache ベースの HTTP クライアントよりもロード時間がかからないとはいえ、機能は限られています。`UrlConnectionHttpClient` クラスの設定については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Configure the URLConnection-based HTTP client](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration-url.html)」を参照してください。

### Netty ベースの HTTP クライアント
<a name="NettyHttpClient"></a>

`NettyNioAsyncHttpClient` クラスは非同期クライアントをサポートします。これは非同期でのデフォルトの選択肢です。`NettyNioAsyncHttpClient` クラスの設定については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Configure the Netty-based HTTP client](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration-netty.html)」を参照してください。

### AWS CRT ベースの HTTP クライアント
<a name="AWSCRTHttpClient"></a>

同期クライアントと非同期クライアントの両方をサポートするオプションには、AWS Common Runtime (CRT) ライブラリに新たに追加された `AwsCrtHttpClient` クラスと `AwsCrtAsyncHttpClient` クラスがあります。他の HTTP クライアントと比較して、AWS CRT は以下を提供します。
+ SDK 起動時間の短縮
+ より小さなメモリフットプリント
+ レイテンシータイムの短縮
+ 接続のヘルス管理
+ DNS ロードバランサー

`AwsCrtHttpClient` クラスと `AwsCrtAsyncHttpClient` クラスの設定については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Configure the AWS CRT-based HTTP clients](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration-crt.html)」を参照してください。

AWS CRT ベースの HTTP クライアントは、既存のアプリケーションとの下位互換性が失われるため、デフォルトではありません。ただし、DynamoDB の場合は、同期と非同期の両方に AWS CRT ベースの HTTP クライアントを使用することをお勧めします。

AWS CRT ベースの HTTP クライアントの概要については、「**AWS Developer Tools Blog」の「[Announcing availability of the AWS CRT HTTP Client in the AWS SDK for Java 2.x](https://aws.amazon.com/blogs/developer/announcing-availability-of-the-aws-crt-http-client-in-the-aws-sdk-for-java-2-x/)」を参照してください。

## HTTP クライアントの設定
<a name="ConfigHttpClient"></a>

クライアントを設定する際には、次のとおりのさまざまな設定オプションを指定できます。
+ API コールのさまざまな側面でのタイムアウトの設定。
+ TCP キープアライブの有効化。
+ エラー発生時の再試行ポリシーの制御。
+ [実行インターセプター](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/interceptors.html)インスタンスが変更できる実行属性の指定。実行インターセプターは、API リクエストと応答の実行をインターセプトするコードを作成できます。これにより、メトリクスの公開やリクエストの変更などのタスクを進行中に実行できます。
+ HTTP ヘッダーの追加や操作。
+ [クライアント側のパフォーマンスメトリクスの追跡](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics.html)を有効にできます。この機能を使用すると、アプリケーション内のサービスクライアントに関するメトリクスを収集し、Amazon CloudWatch で出力を分析できます。
+ 非同期の再試行やタイムアウトタスクなどのタスクのスケジュール設定に使用する代替エグゼキュータサービスを指定できます。

設定を制御するには、[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html) オブジェクトをサービスクライアントの `Builder` クラスに提供します。これについては、次のセクションのコードサンプルのいくつかで説明します。

`ClientOverrideConfiguration` では、標準的な設定のオプションが提供されます。プラガブル HTTP クライアントによっては、実装に応じた設定もできます。

**Topics**
+ [

### タイムアウト設定
](#TimeoutConfig)
+ [

### RetryMode
](#RetryMode)
+ [

### DefaultsMode
](#DefaultsMode)
+ [

### キープアライブの設定
](#KeepAliveConfig)

### タイムアウト設定
<a name="TimeoutConfig"></a>

クライアントの設定を調整して、サービスの呼びだしに関連するさまざまなタイムアウトを制御できます。DynamoDB は、その他の AWS のサービス サービスと比較してレイテンシーが低減します。このため、ネットワークに問題が発生した場合のフェイルファストを実現するように、プロパティを調整してタイムアウト値を低く指定することをお勧めします。

DynamoDB クライアントで `ClientOverrideConfiguration` を使用するか、基盤となる HTTP クライアント実装で詳細な設定オプションを変更することによって、レイテンシーに関する動作をカスタマイズできます。

以下の影響を左右するプロパティを設定するには、`ClientOverrideConfiguration` を使用できます。
+ `apiCallAttemptTimeout` — HTTP リクエストの 1 回の試行が完了するまで、諦めてタイムアウトになるまで待機する時間。
+ `apiCallTimeout` – クライアントで API コールを完了するまでに許容される時間。これには、再試行を含むすべての HTTP リクエストで設定されるリクエストハンドラーの実行が含まれます。

接続タイムアウトやソケットタイムアウトなど、タイムアウトオプションによっては、AWS SDK for Java 2.x は、[デフォルト値](https://github.com/aws/aws-sdk-java-v2/blob/a0c8a0af1fa572b16b5bd78f310594d642324156/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java#L134)を提供します。SDK は、API コールのタイムアウトや個別の API コールの試行タイムアウトのデフォルト値は提供していません。このようなタイムアウトが `ClientOverrideConfiguration` で設定されていない場合、SDK は全体的な API コールタイムアウトの代わりにソケットのタイムアウト値を使用します。ソケットのタイムアウトのデフォルト値は 30 秒です。

### RetryMode
<a name="RetryMode"></a>

タイムアウト設定に関して考慮すべきもう 1 つの設定は、`RetryMode` 設定オブジェクトです。この設定オブジェクトには、再試行動作のコレクションが含まれています。

SDK for Java 2.x は、次の再試行モードをサポートしています。
+ `legacy` — 明示的に変更しない場合のデフォルトの再試行モード。この再試行モードは Java SDK 固有のものです。このモードでは、最大 3 回まで再試行でき、DynamoDB などのサービスの場合は最大 8 回まで再試行できます。
+ `standard` — 他の AWS SDK との整合性が高いことから、「standard」と名付けられています。このモードでは、最初の再試行で 0 ミリ秒から 1,000 ミリ秒の範囲のランダムな期間だけ待機します。もう一度再試行が必要な場合は、このモードは 0 ミリ秒から 1,000 ミリ秒までの別のランダムな期間を選択して、これを 2 倍します。さらに再試行が必要な場合は、このモードは同じようにランダムな時間を選択し、これに 4 を掛け、試行を続けます。各待機時間の上限は 20 秒です。このモードは、検出された障害条件の数が `legacy` モードよりも多い場合に再試行を実行します。DynamoDB の場合、[numRetries](#numRetries) でオーバーライドしない限り、最大合計 3 回の試行が実行されます。
+ `adaptive` — `standard` モードに基づいて構築されています。成功率を最大化するために AWS リクエスト率を動的に制限します。これにより、リクエストのレイテンシーが増大する場合があります。予測可能なレイテンシーが重要な場合は、アダプティブ再試行モードはお勧めしません。

このような再試行モードの詳細な定義については、「**AWS SDK とツールのリファレンスガイド」の「[再試行動作](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html)」トピックを参照してください。

#### 再試行ポリシー
<a name="RetryPolicies"></a>

すべての `RetryMode` 設定には、単一または複数の [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/RetryCondition.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/RetryCondition.html) 設定に基づいて構築される [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/RetryPolicy.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/RetryPolicy.html) があります。[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/TokenBucketRetryCondition.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/TokenBucketRetryCondition.html) は、DynamoDB SDK クライアント実装の再試行動作には、特に重要です。この条件は、トークンバケットアルゴリズムを使用して SDK が行う再試行の数を制限します。選択した再試行モードに応じて、スロットリング例外によって `TokenBucket` からトークンが減算される場合と減算されない場合があります。

クライアントでスロットリング例外や一時的なサーバーエラーなどの再試行できるエラーが発生すると、SDK は自動的にリクエストを再試行します。このような再試行の回数と頻度は制御できます。

クライアントを設定する際、以下のパラメータをサポートする `RetryPolicy` を指定できます。
+ `numRetries` — リクエストが失敗したとみなされるまでに適用すべき最大再試行回数。使用する再試行モードを問わず、デフォルト値は 8 です。
**警告**  
このデフォルト値は、慎重に考慮した上で変更してください。
+ `backoffStrategy` - 再試行に適用する [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/BackoffStrategy.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/BackoffStrategy.html)。デフォルト戦略は [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/FullJitterBackoffStrategy.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/FullJitterBackoffStrategy.html) です。この戦略は、現在の再試行回数、ベースとなる遅延、最大バックオフ時間に基づいて、追加の再試行の間に指数関数的な遅延を実行します。次に、ジッターを追加して、多少のランダム性を提供します。指数関数的遅延で使用される基本遅延は、再試行モードを問わず 25 ミリ秒です。
+ `retryCondition` – [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/RetryCondition.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/RetryCondition.html) は、リクエストを再試行するかどうかを決定します。デフォルトでは、再試行可能と思われる特定の HTTP ステータスコードと例外のセットを再試行します。ほとんどの場合、このデフォルトの設定で十分です。

次のコードは代替再試行ポリシーを提供します。合計で 5 回の再試行 (合計 6 回のリクエスト) を指定します。最初の再試行は約 100 ミリ秒の遅延の後に実行され、追加の再試行ごとにその時間が指数関数的に倍増され、最大 1 秒の遅延が発生します。

```
DynamoDbClient client = DynamoDbClient.builder()
    .overrideConfiguration(ClientOverrideConfiguration.builder()
        .retryPolicy(RetryPolicy.builder()
            .backoffStrategy(FullJitterBackoffStrategy.builder()
                .baseDelay(Duration.ofMillis(100))
                .maxBackoffTime(Duration.ofSeconds(1))
                .build())
            .numRetries(5)
            .build())
        .build())
    .build();
```

### DefaultsMode
<a name="DefaultsMode"></a>

`ClientOverrideConfiguration` と `RetryMode` が管理しないタイムアウトプロパティは、通常、`DefaultsMode` を指定することで暗黙的に設定されます。

AWS SDK for Java 2.x (バージョン 2.17.102 以降) では、`DefaultsMode` のサポートが導入されました。この機能は、HTTP 通信設定、再試行動作、サービスのリージョンエンドポイント設定、他の SDK 関連の構成など、一般的で設定可能な設定のデフォルト値のセットを提供します。この機能を使用すると、一般的な使用シナリオに合わせて新しい設定のデフォルトを指定できます。

デフォルトモードはすべての AWS SDK で標準化されています。SDK for Java 2.x は、次のデフォルトモードをサポートしています。
+ `legacy` — AWS SDK によって異なり、`DefaultsMode` が確立される前に存在していたデフォルト設定を使用します。
+ `standard` — ほとんどのシナリオで、最適化されていないデフォルト設定を提供します。
+ `in-region` — 標準モードに基づいて構築されており、同じ AWS リージョン 内から AWS のサービス を呼び出すアプリケーションにカスタマイズされた最適化が含まれています。
+ `cross-region` — 標準モードに基づいて構築されており、異なるリージョンの AWS のサービス を呼び出すアプリケーション向けにタイムアウトを長く指定した設定が含まれています。
+ `mobile` — 標準モードに基づいて構築されており、レイテンシーの長いモバイルアプリケーション向けにカスタマイズした、タイムアウト時間を長く指定した設定が含まれています。
+ `auto` – 標準モードに基づいて構築されており、実験的な機能が含まれています。SDK はランタイム環境を検出して適切な設定を自動的に決定しようとします。自動検出はヒューリスティックベースで、100% の精度が得られるとは限りません。ランタイム環境が特定できない場合は、標準モードを使用します。自動検出を行うと、[インスタンスのメタデータとユーザデータ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)がクエリされる可能性があり、これによりレイテンシーが発生する場合があります。起動時のレイテンシーがアプリケーションにとって最重要な場合は、代わりに明示的な `DefaultsMode` を選択することをおすすめします。

デフォルトモードは次の方法で設定できます。
+ `AwsClientBuilder.Builder#defaultsMode(DefaultsMode)` を介した直接クライアントでの設定。
+ `defaults_mode` プロファイルファイルプロパティを使用した設定プロファイルでの設定。
+ `aws.defaultsMode` システムプロパティを使用したグローバル設定。
+ `AWS_DEFAULTS_MODE` 環境変数を使用したグローバル設定。

**注記**  
`legacy` 以外のモードでは、ベストプラクティスの進化に応じて、提供されるデフォルト値が変更される可能性があります。そのため、`legacy` 以外のモードを使用している場合は、SDK をアップグレードする際にテストを実施することをお勧めします。

「**AWS SDK とツールのリファレンスガイド」の「[スマート設定デフォルト](https://docs.aws.amazon.com/sdkref/latest/guide/feature-smart-config-defaults.html)」には、さまざまなデフォルトモードでの設定プロパティとデフォルト値の一覧が記載されています。

デフォルトのモード値は、アプリケーションの特性と、アプリケーションが操作する AWS のサービス に基づいて選択します。

デフォルト値は、幅広い AWS のサービス が選択されることを考慮して設定されています。DynamoDB テーブルとアプリケーションの両方が単一のリージョンにデプロイされる典型的な DynamoDB デプロイの場合、`standard` デフォルトモードの中で最も関連性があるのは `in-region` のデフォルトモードです。

**Example 低レイテンシーの呼び出し向けに調整した DynamoDB SDK クライアントの設定**  
次の例では、低レイテンシーが期待される DynamoDB 呼び出し向けにタイムアウトをより低い値に調整します。  

```
DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.builder()
    .defaultsMode(DefaultsMode.IN_REGION)
    .httpClientBuilder(AwsCrtAsyncHttpClient.builder())
    .overrideConfiguration(ClientOverrideConfiguration.builder()
        .apiCallTimeout(Duration.ofSeconds(3))
        .apiCallAttemptTimeout(Duration.ofMillis(500))
        .build())
    .build();
```
個別の HTTP クライアント実装により、タイムアウトと接続使用の動作はさらに詳細に制御できます。例えば、AWS CRT ベースのクライアントの場合、`ConnectionHealthConfiguration` を有効にすると、クライアントは使用される接続のヘルスをアクティブにモニタリングできます。詳細については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Advanced configuration of AWS CRT-based HTTP clients](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration-crt.html#configuring-the-crt-based-http-client)」を参照してください。

### キープアライブの設定
<a name="KeepAliveConfig"></a>

キープアライブを有効にすると、接続を再利用することでレイテンシーを短縮できます。キープアライブには、HTTP キープアライブと TCP キープアライブの 2 種類があります。
+ HTTP キープアライブは、その後のリクエストで接続を再利用できるように、クライアントとサーバー間の HTTPS 接続の維持を試行します。これにより、重い HTTPS 認証がその後のリクエストでスキップされます。HTTP キープアライブはすべてのクライアントでデフォルトで有効になっています。
+ TCP キープアライブは、基盤となるオペレーティングシステムに対して、ソケット接続を介して小型のパケットを送信するようにリクエストします。これにより、ソケットが維持されることがさらに保証され、ドロップを即座に検出できます。これにより、ドロップしたソケットの使用にその後のリクエストが時間を費やす必要がなくなります。TCP キープアライブは、デフォルトではすべてのクライアントで無効になっています。以下のコードサンプルは、各 HTTP クライアントでこれを有効化する方法を示しています。CRT ベース以外のすべての HTTP クライアントの場合、キープアライブを有効にすると、実際のキープアライブメカニズムはオペレーティングシステムに依存します。このため、タイムアウトやパケット数など、追加の TCP キープアライブ値をオペレーティングシステムで設定する必要があります。これを実行するには、Linux または macOS では `sysctl` を使用し、Windows ではレジストリ値を使用します。

**Example Apache ベースの HTTP クライアントで TCP キープアライブを有効にするには**  

```
DynamoDbClient client = DynamoDbClient.builder()
    .httpClientBuilder(ApacheHttpClient.builder().tcpKeepAlive(true))
    .build();
```

**`URLConnection` ベースの HTTP クライアント**  
`URLConnection` ベースの HTTP クライアント [https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html](https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html) を使用する同期クライアントには、キープアライブを有効にする[メカニズム](https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html)はありません。

**Example Netty ベースの HTTP クライアントで TCP キープアライブを有効にするには**  

```
DynamoDbAsyncClient client = DynamoDbAsyncClient.builder()
    .httpClientBuilder(NettyNioAsyncHttpClient.builder().tcpKeepAlive(true))
    .build();
```

**Example AWS CRT ベースの HTTP クライアントで TCP キープアライブを有効にするには**  
AWS CRT ベースの HTTP クライアントを使用すると、TCP キープアライブを有効にして、実行時間を制御できます。  

```
DynamoDbClient client = DynamoDbClient.builder()
    .httpClientBuilder(AwsCrtHttpClient.builder()
    .tcpKeepAliveConfiguration(TcpKeepAliveConfiguration.builder()
        .keepAliveInterval(Duration.ofSeconds(50))
        .keepAliveTimeout(Duration.ofSeconds(5))
        .build()))
    .build();
```
非同期の DynamoDB クライアントを使用する場合は、次のコードのとおり TCP キープアライブを有効にすることができます。  

```
DynamoDbAsyncClient client = DynamoDbAsyncClient.builder()
    .httpClientBuilder(AwsCrtAsyncHttpClient.builder()
    .tcpKeepAliveConfiguration(TcpKeepAliveConfiguration.builder()
        .keepAliveInterval(Duration.ofSeconds(50))
        .keepAliveTimeout(Duration.ofSeconds(5))
        .build()))
    .build();
```

## エラー処理
<a name="JavaErrorHandling"></a>

例外処理については、AWS SDK for Java 2.x ではランタイム (非チェック) 例外を使用します。

すべての SDK 例外をカバーする基本となる例外は、Java 非チェック `RuntimeException` の拡張である [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html) です。これをキャッチすると、SDK からスローされるすべての例外をキャッチできます。

`SdkServiceException` には、[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsServiceException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsServiceException.html) というサブクラスがあります。このサブクラスは、AWS のサービス との間の通信に問題があることを示します。これには、DynamoDB との通信の問題を示す [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html) というサブクラスがあります。これをキャッチすると、DynamoDB に関連するすべての例外はキャッチできますが、他の SDK 例外はキャッチできません。

`DynamoDbException` には、さらに具体的な[例外タイプ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html)もあります。このような例外タイプの中には、[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/TableAlreadyExistsException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/TableAlreadyExistsException.html) などのコントロールプレーンの操作に適用されるものもあります。データプレーン操作に適用されるものもあります。一般的なデータプレーン例外の例は、以下のとおりです。
+ [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ConditionalCheckFailedException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ConditionalCheckFailedException.html) — リクエストに false と評価される条件を指定しました。たとえば、項目に条件付き更新を実行しようとしたかもしれませんが、属性の実際の値は、条件の予期される値と一致しませんでした。この方法で失敗したリクエストは再試行されません。

その他の状況については、特定の例外は定義されていません。例えば、リクエストがスロットリングすると、特定の `ProvisionedThroughputExceededException` がスローされ、その他の場合にはより一般的な `DynamoDbException` がスローされる可能性があります。いずれの場合も、`isThrottlingException()` が `true` を返したかを確認することで、例外がスロットリングによって引き起こされたかどうかを判断できます。

アプリケーションのニーズに応じて、すべての `AwsServiceException` インスタンスまたは `DynamoDbException` インスタンスをキャッチできます。ただし多くの場合、状況に応じて異なる動作が必要になります。条件チェックの失敗を処理するロジックは、スロットリングを処理するロジックとは異なります。どの例外パスに対処するかを定義して、代替パスは必ずテストしてください。テストの実施は、関連するすべてのシナリオに確実に対処できるようにするうえで役立ちます。

よく発生するエラーのリストについては、「[DynamoDB でのエラー処理](Programming.Errors.md)」を参照してください。また、「**Amazon DynamoDB API Reference」の「[Common Errors](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/CommonErrors.html)」も参照してください。この API Reference には、[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) オペレーションなど、各 API オペレーションで発生する可能性のある厳密なエラーも記載されています。例外処理の詳細については、「**AWS SDK for Java 2.x デベロッパーガイド」の「[Exception handling for the AWS SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/handling-exceptions.html)」を参照してください。

## AWS リクエスト ID
<a name="JavaRequestID"></a>

各リクエストにはリクエスト ID が含まれており、AWS サポート と連携して問題を診断する場合に取得すると便利です。`SdkServiceException` から派生した各例外には、リクエスト ID を取得できる [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html#requestId()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html#requestId()) メソッドがあります。

## ログ記録
<a name="JavaLogging"></a>

SDK が提供するログ記録を使用すると、クライアントライブラリから重要なメッセージをキャッチする場合や、より詳細なデバッグを行う場合の両方で役に立ちます。ロガーは階層化されており、SDK はルートロガーとして `software.amazon.awssdk` を使用します。レベルは、`TRACE`、`DEBUG`、`INFO`、`WARN`、`ERROR`、`ALL`、または `OFF` のいずれかを使用して設定できます。設定したレベルは、そのロガーとロガー階層の下位レベルに適用されます。

AWS SDK for Java 2.x は、ログ記録に Simple Logging Façade for Java (SLF4J) を使用します。これは他のロガーの抽象化レイヤーとして機能し、これを使用して希望するロガーをプラグインできます。ロガーの接続方法については、「[SLF4J ユーザーマニュアル](https://www.slf4j.org/manual.html)」を参照してください。

各ロガーには特定の動作があります。Log4j 2.x ロガーは、デフォルトで、ログイベントを `System.out` に追加する `ConsoleAppender` を作成し、デフォルトで `ERROR` ログレベルを設定します。

SLF4J に含まれる SimpleLogger ロガーは、デフォルトで `System.err` を出力し、ログレベルはデフォルトで `INFO` になります。

出力量を制限しながら、SDK のクライアントライブラリから重要なメッセージをキャッチできるように、本番環境のデプロイでは `software.amazon.awssdk` のレベルを `WARN` に設定することをお勧めします。

SLF4J がクラスパス上でサポートされているロガーを見つけられない場合 (SLF4J バインディングがない場合)、SLF4J はデフォルトで [no operation implementation](https://www.slf4j.org/codes.html#noProviders) になります。この実装により、SLF4J がクラスパス上でロガー実装を見つけられなかったことを説明するメッセージが `System.err` に記録されます。このような状況を防ぐには、ロガー実装を追加する必要があります。これを実行するには、Apache Maven の `pom.xml` に `org.slf4j.slf4j-simple` や `org.apache.logging.log4j.log4j-slf4j2-imp` などのアーティファクトに対する依存関係を追加します。

アプリケーション構成へのログ記録依存関係の追加など、SDK でのログ記録の構成方法については、「**AWS SDK for Java デベロッパーガイド」の「[Logging with the SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/logging-slf4j.html)」を参照してください。

`Log4j2.xml` ファイルの次の設定では、Apache Log4j 2 ロガーを使用している場合にログ記録の動作を調整する方法を示しています。この設定では、ルートロガーレベルは `WARN` に設定しています。このログレベルは、`software.amazon.awssdk` ロガーなど、階層内のすべてのロガーに継承されます。

デフォルトでは、出力は `System.out` に送信されます。次の例では、デフォルトの出力 Log4j アペンダを上書きして、カスタマイズした Log4j `PatternLayout` を適用します。

**`Log4j2.xml` 設定ファイルの例**  
次の設定では、すべてのロガー階層のコンソールに `ERROR` レベルと `WARN` レベルのメッセージがログ記録されます。

```
<Configuration status="WARN">
  <Appenders>
    <Console name="ConsoleAppender" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
    </Console>
  </Appenders>

  <Loggers>
    <Root level="WARN">
      <AppenderRef ref="ConsoleAppender"/>
    </Root>
  </Loggers>
</Configuration>
```

### AWS リクエスト ID のログ記録
<a name="JavaReqIDLogging"></a>

何らかの問題が発生した場合、例外内でリクエスト ID を検索できます。ただし、例外を生成していないリクエストのリクエスト ID が必要な場合は、ログ記録を使用できます。

リクエスト ID は、`DEBUG` ロガーによって `software.amazon.awssdk.request` レベルで出力されます。次の例は、前の [configuration example](#Log4j2ConfigEg) を拡張して、ルートロガーのレベルを `ERROR`、`software.amazon.awssdk` のレベルを `WARN`、`software.amazon.awssdk.request` のレベルを `DEBUG` に維持します。このようなレベルを設定すると、リクエスト ID や、エンドポイント、ステータスコードなどのその他のリクエストに関する詳細を取得するうえで役立ちます。

```
<Configuration status="WARN">
  <Appenders>
    <Console name="ConsoleAppender" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
    </Console>
  </Appenders>

  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="ConsoleAppender"/>
    </Root>
    <Logger name="software.amazon.awssdk" level="WARN" />
    <Logger name="software.amazon.awssdk.request" level="DEBUG" />
  </Loggers>
</Configuration>
```

ログ出力の例を次に示します。

```
2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Sending Request: DefaultSdkHttpFullRequest(httpMethod=POST, protocol=https, host=dynamodb.us-east-1.amazonaws.com, encodedPath=/, headers=[amz-sdk-invocation-id, Content-Length, Content-Type, User-Agent, X-Amz-Target], queryParameters=[])
 2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Received successful response: 200, Request ID: QS9DUMME2NHEDH8TGT9N5V53OJVV4KQNSO5AEMVJF66Q9ASUAAJG, Extended Request ID: not available
```

## Pagination (ページ分割)
<a name="JavaPagination"></a>

[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) や [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html) など、リクエストによっては、1 回のリクエストで返されるデータのサイズが制限され、後続のページを取得するにはリクエストを繰り返し行う必要がある場合があります。

各ページで読み取られる項目の最大数は、`Limit` パラメータを使用して制御できます。`Limit` パラメータを使用すると、例えば、最後の 10 項目のみを取得することができます。この制限は、フィルタリングが適用される前にテーブルから読み込む項目の上限数を指定します。フィルタリングの結果を 10 項目に正確に指定する方法はありません。事前にフィルタリング済みの数を制御し、実際に 10 項目を取得した場合にのみクライアント側でチェックできます。制限にかかわらず、すべての応答の最大サイズは常に 1 MB です。

API レスポンスには `LastEvaluatedKey` が含まれる場合があります。これは、制限数または制限サイズに達したためにレスポンスが終了したことを示します。このキーは、応答のために評価された最後のキーです。API を直接操作して、この `LastEvaluatedKey` を取得し、それを `ExclusiveStartKey` として後続の呼び出しに渡し、その開始点から次のチャンクを読み取ることができます。`LastEvaluatedKey` が返されない場合は、`Query` または `Scan` API コールに一致する項目がもうなかったことを意味します。

次の例では、低レベルインターフェイスを使用しており、`keyConditionExpression` パラメータに基づいて項目が 100 に制限されます。

```
QueryRequest.Builder queryRequestBuilder = QueryRequest.builder()
        .expressionAttributeValues(Map.of(
                ":pk_val", AttributeValue.fromS("123"),
                ":sk_val", AttributeValue.fromN("1000")))
        .keyConditionExpression("pk = :pk_val AND sk > :sk_val")
        .limit(100)
        .tableName(TABLE_NAME);

while (true) {
    QueryResponse queryResponse = DYNAMODB_CLIENT.query(queryRequestBuilder.build());

    queryResponse.items().forEach(item -> {
        LOGGER.info("item PK: [" + item.get("pk") + "] and SK: [" + item.get("sk") + "]");
    });

    if (!queryResponse.hasLastEvaluatedKey()) {
        break;
    }
    queryRequestBuilder.exclusiveStartKey(queryResponse.lastEvaluatedKey());
}
```

AWS SDK for Java 2.x では、複数のサービスコールを実行して、結果の次のページを自動的に取得する自動ページ分割メソッドを提供し、DynamoDB の操作を簡素化します。これによりコードが簡素化されます。ただし、ページを手動で読み取ることで維持していたリソース使用量がある程度制御できなくなります。

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html#queryPaginator(software.amazon.awssdk.services.dynamodb.model.QueryRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html#queryPaginator(software.amazon.awssdk.services.dynamodb.model.QueryRequest)) や [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html#scanPaginator(software.amazon.awssdk.services.dynamodb.model.ScanRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html#scanPaginator(software.amazon.awssdk.services.dynamodb.model.ScanRequest)) など、DynamoDB クライアントで利用可能な `Iterable` メソッドを使用すると、SDK がページ分割を処理します。このようなメソッドの戻り値の型はカスタム iterable で、これを使用してすべてのページを反復処理できます。SDK は内部でサービス呼び出しを処理します。Java Stream API を使用すると、次の例に示すとおり `QueryPaginator` の結果を処理できます。

```
QueryPublisher queryPublisher =
    DYNAMODB_CLIENT.queryPaginator(QueryRequest.builder()
        .expressionAttributeValues(Map.of(
            ":pk_val", AttributeValue.fromS("123"),
            ":sk_val", AttributeValue.fromN("1000")))
        .keyConditionExpression("pk = :pk_val AND sk > :sk_val")
        .limit(100)
        .tableName("YourTableName")
        .build());

queryPublisher.items().subscribe(item ->
    System.out.println(item.get("itemData"))).join();
```

## データクラス注釈
<a name="JavaDataClassAnnotation"></a>

Java SDK は、データクラスの属性に追加できるいくつかのアノテーションを提供します。このようなアノテーションは、SDK が属性を処理する方法に影響します。アノテーションを追加すると、属性を暗黙的なアトミックカウンタとして動作させたり、自動生成したタイムスタンプ値を維持したり、項目のバージョン番号を追跡したりできます。詳細については、「[データクラスのアノテーション](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)」を参照してください。

# DynamoDB でのエラー処理
<a name="Programming.Errors"></a>

 このセクションでは、ランタイムエラーとその処理方法について説明します。同時に、Amazon DynamoDB に特有のエラーメッセージとコードについて説明します。AWS のすべてのサービスに共通するエラーのリストについては、「[アクセス管理](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/CommonErrors.html)」を参照してください。

**Topics**
+ [

## エラーコンポーネント
](#Programming.Errors.Components)
+ [

## トランザクションエラー
](#Programming.Errors.TransactionalErrors)
+ [

## エラーメッセージおよびコード
](#Programming.Errors.MessagesAndCodes)
+ [

## アプリケーションのエラー処理
](#Programming.Errors.Handling)
+ [

## エラーの再試行とエクスポネンシャルバックオフ
](#Programming.Errors.RetryAndBackoff)
+ [

## バッチオペレーションとエラー処理
](#Programming.Errors.BatchOperations)

## エラーコンポーネント
<a name="Programming.Errors.Components"></a>

プログラムがリクエストを送信すると、DynamoDB はその処理を実行するよう試みます。リクエストが成功した場合、DynamoDB はそのオペレーションが出力した結果とともに、 HTTP の成功ステータスコード (`200 OK`) を返します。

リクエストが正常に行われなかった場合、DynamoDB はエラーを返します。それぞれのエラーには、次の三つのコンポーネントがあります: 
+ HTTP ステータスコード (`400` など)。
+ 例外の名前 (`ResourceNotFoundException` など)。
+ エラーメッセージ (`Requested resource not found: Table: tablename not found` など)。

AWS SDK によりアプリケーションにエラーが伝達されるため、適切なアクションを実行できます。たとえば、Java プログラムでは、 `try-catch` を処理する `ResourceNotFoundException` ロジックを記述できます。

AWS SDK を使用していない場合は、DynamoDB からの低レベルのレスポンスの内容を、ユーザー側で解析する必要があります。以下に、そのようなレスポンスの例を示します。

```
HTTP/1.1 400 Bad Request
x-amzn-RequestId: LDM6CJP8RMQ1FHKSC1RBVJFPNVV4KQNSO5AEMF66Q9ASUAAJG
Content-Type: application/x-amz-json-1.0
Content-Length: 240
Date: Thu, 15 Mar 2012 23:56:23 GMT

{"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",
"message":"Requested resource not found: Table: tablename not found"}
```

## トランザクションエラー
<a name="Programming.Errors.TransactionalErrors"></a>

トランザクションエラーの詳細については、「[DynamoDB でのトランザクション競合の処理](transaction-apis.md#transaction-conflict-handling)」を参照してください。

## エラーメッセージおよびコード
<a name="Programming.Errors.MessagesAndCodes"></a>

以下に、DynamoDB によって返される例外のリストを、HTTP ステータスコードでグループ分けして示します。*再試行してもいいですか*が*はい*であれば、同じリクエストを再度送信できます。*再試行してもいいですか*が*いいえ*であれば、新しいリクエストを送信する前に、クライアント側で問題を修正する必要があります。

### HTTP ステータスコード 400
<a name="Programming.Errors.MessagesAndCodes.http400"></a>

HTTP ステータスコード`400`は、認証の失敗、必須パラメータの欠落、またはテーブルにプロビジョニングされているスループットの超過などのリクエストに関連した問題があることを示しています。リクエストを再度送信する前に、アプリケーションで問題を修正する必要があります。

**AccessDeniedException **  
メッセージ: *アクセスが拒否されました。*  
クライアントがリクエストに正しく署名しませんでした。AWS SDK を使用している場合には、リクエストへの署名が自動的に実行されます。使用していない場合は、「*AWS 全般のリファレンス*」の「[署名バージョン 4 の署名プロセス](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)」に進んでください。  
再試行してもいいですか。いいえ

**ConditionalCheckFailedException**  
メッセージ: *条件付きリクエストが失敗しました。*  
false と評価された条件を指定しました。たとえば、項目に条件付き更新を実行しようとしたかもしれませんが、属性の実際の値は、条件の予期される値と一致しませんでした。  
再試行してもいいですか。いいえ

**IncompleteSignatureException**  
メッセージ: *リクエストの署名が AWS スタンダードに適合しません。*  
リクエストの署名に、必要なすべての要素が含まれていませんでした。AWS SDK を使用している場合には、リクエストへの署名が自動的に実行されます。使用していない場合は、「*AWS 全般のリファレンス*」の「[署名バージョン 4 の署名プロセス](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)」に進んでください。  
再試行してもいいですか。いいえ

**ItemCollectionSizeLimitExceededException**  
メッセージ: *コレクションサイズが超過しました。*  
ローカルセカンダリインデックスがあるテーブルにおいて、同じパーティションキー値を持つ項目のグループが占めるサイズが、最大 10 GB の上限を超過しました。項目コレクションの詳細については、「[ローカルセカンダリインデックス内の項目コレクション](LSI.md#LSI.ItemCollections)」を参照してください。  
再試行してもいいですか。はい

**LimitExceededException**  
メッセージ: *特定の受信者に対するオペレーションが多すぎます。*  
同時オペレーションのコントロールプレーンが多すぎます。`CREATING`、`DELETING`、または `UPDATING` の状態のテーブルやインデックスの累積数が、500 を超えることはできません。  
再試行してもいいですか。はい

**MissingAuthenticationTokenException**  
メッセージ: *リクエストには、有効な (登録済みメンバー) AWS アクセスキー ID が含まれている必要があります。*  
リクエストに、必要な認可ヘッダーが含まれていないか、または正しい形式ではありません。「」を参照してください[DynamoDB 低レベル API](Programming.LowLevelAPI.md)  
再試行してもいいですか。いいえ

**ProvisionedThroughputExceededException**  
メッセージ: *1 つのテーブルまたは 1 つ以上のグローバルセカンダリインデックスで、プロビジョン済みスループットが、許容されている最大量を超えました。プロビジョンドスループットと消費スループットのパフォーマンスメトリクスを表示するには、「[Amazon CloudWatch コンソール](https://console.aws.amazon.com/cloudwatch/home)」を参照してください。*  
エラーには、スロットリングが発生した理由に関する特定のコンテキストを提供する `ThrottlingReason` フィールドのリストが含まれ、形式は `ResourceType+OperationType+LimitType` (例: `TableReadProvisionedThroughputExceeded`) と、影響を受けるリソースの ARN です。これにより、スロットリング対象のリソース (テーブルまたはインデックス)、スロットリングをトリガーしたオペレーションタイプ (読み取りまたは書き込み)、および超過した特定の制限 (この場合はプロビジョンドキャパシティ) を特定できます。スロットリングの問題の診断と解決の詳細については、「[スロットリングの診断](throttling-diagnosing-workflow.md)」を参照してください。  
例: リクエストの頻度が多すぎます。DynamoDB 用の AWS SDK では、この例外を受け取ったリクエストを自動的に再試行します。リクエストは最終的に成功しますが、再試行キューが大きすぎて終了しない場合もあります。[エラーの再試行とエクスポネンシャルバックオフ](#Programming.Errors.RetryAndBackoff) を使用して、リクエストの頻度を少なくします。  
再試行してもいいですか。はい

**ReplicatedWriteConflictException**  
メッセージ: *このリクエスト内の 1 つ以上の項目が、別のリージョンのリクエストによって変更されています。*  
例: マルチリージョンの強力な整合性 (MRSC) グローバルテーブル内の項目に対して書き込み操作がリクエストされましたが、現在別のリージョンのリクエストによって変更されています。  
再試行してもいいですか。はい

**RequestLimitExceeded**  
メッセージ: *スループットがアカウントの現在のスループット制限を超えています。制限の引き上げをリクエストするには、[https://aws.amazon.com/support](https://aws.amazon.com/support) で AWS サポートにお問い合わせください。*  
エラーには、スロットリングが発生した理由に関する特定のコンテキストを提供する `ThrottlingReason` フィールドのリストが含まれ、形式は `ResourceType+OperationType+LimitType` (例: `TableWriteAccountLimitExceeded` または `IndexReadAccountLimitExceeded`) と、影響を受けるリソースの ARN です。これにより、スロットリング対象のリソース (テーブルまたはインデックス)、スロットリングをトリガーしたオペレーションタイプ (読み取りまたは書き込み)、アカウントレベルのサービスクォータを超えたことを確認できます。スロットリングの問題の診断と解決の詳細については、「[スロットリングの診断](throttling-diagnosing-workflow.md)」を参照してください。  
例: オンデマンドリクエストの速度が、許容されているアカウントスループットを超えていて、これ以上テーブルをスケールできません。  
再試行してもいいですか。はい

**ResourceInUseException**  
メッセージ: *変更しようとしているリソースは使用中です。*  
例: 既存のテーブルを再作成しようとしたか、`CREATING` 状態にあるテーブルを削除しようとしました。  
再試行してもいいですか。いいえ

**ResourceNotFoundException **  
メッセージ: *リクエストされたリソースは存在しません。*  
例: リクエストされたテーブルが存在しないか、ごく初期の `CREATING` 状態にあります。  
再試行してもいいですか。いいえ

**ThrottlingException**  
メッセージ: *リクエストの速度が、許容されているスループットを超えています。*  
この例外は、AmazonServiceException レスポンスとして、TROTTLING\$1EXCEPTION ステータスコードとともに返されます。この例外は、[コントロールプレーン](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.API.html#HowItWorks.API.ControlPlane) API オペレーションの実行が速すぎる場合に返される可能性があります。  
オンデマンドモードを使用するテーブルの場合、リクエストレートが高すぎると、[データプレーン](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.API.html#HowItWorks.API.DataPlane) API オペレーションでこの例外が返されることがあります。オンデマンドスケーリングの詳細については、「[初期スループットとスケーリングのプロパティ](on-demand-capacity-mode.md#on-demand-capacity-mode-initial)」を参照してください。  
エラーには、スロットリングが発生した理由に関する特定のコンテキストを提供する `ThrottlingReason` フィールドのリストが含まれ、形式は `ResourceType+OperationType+LimitType` (例: `TableReadKeyRangeThroughputExceeded` または `IndexWriteMaxOnDemandThroughputExceeded`) と、影響を受けるリソースの ARN です。この情報は、スロットリング対象のリソース (テーブルまたはインデックス)、スロットリングをトリガーしたオペレーションタイプ (読み取りまたは書き込み)、および超過した特定の制限 (パーティション制限またはオンデマンドの最大スループット) を特定するのに役立ちます。スロットリングの問題の診断と解決の詳細については、「[スロットリングの診断](throttling-diagnosing-workflow.md)」を参照してください。  
再試行してもいいですか。はい

**UnrecognizedClientException**  
メッセージ: *アクセスキー ID またはセキュリティトークンが無効です。*  
リクエスト署名が間違っています。最も可能性の高い原因は、AWS アクセスキー ID またはシークレットキーが無効であることです。  
再試行してもいいですか。はい

**ValidationException**  
メッセージ: 発生した特定のエラーにより異なります  
このエラーは、必須パラメータが指定されていない、値が範囲外である、データ型が一致しない、などいくつかの理由で発生します。エラーメッセージに、エラーを引き起こしたリクエストの特定部分に関する詳細が含まれています。  
再試行してもいいですか。いいえ

### HTTP ステータスコード 5xx
<a name="Programming.Errors.MessagesAndCodes.http5xx"></a>

HTTP ステータスコード `5xx` は、AWS で解決する必要のある問題を示しています。これは一時的なエラーかもしれず、その場合はリクエストを再試行することで成功する場合があります。それ以外の場合、サービスにオペレーション上の問題があるかどうかを確認するために、[AWS Service Health Dashboard](https://status.aws.amazon.com/) を参照してください。

詳細については、「[Amazon DynamoDB の HTTP 5xx エラーを解決する方法を教えてください。](https://aws.amazon.com/premiumsupport/knowledge-center/dynamodb-http-5xx-errors/)」を参照してください。

**InternalServerError (HTTP 500)**  
DynamoDB はリクエストを処理できませんでした。  
再試行してもいいですか。はい  
項目の操作中に内部サーバーエラーが発生することがあります。これはテーブルの存続期間中に発生すると予想されます。失敗したリクエストは速やかに再試行できます。  
書き込みオペレーションでステータスコード 500 を受け取った場合、オペレーションは成功した可能性も、失敗した可能性もあります。書き込みオペレーションが `TransactWriteItem` リクエストである場合、オペレーションを再試行できる状態です。書き込みオペレーションが単一項目の書き込み要求 (`PutItem`、`UpdateItem`、または `DeleteItem` など) である場合、アプリケーションはオペレーションを再試行する前に項目の状態を読み取り、[DynamoDB 条件式 CLI の例](Expressions.ConditionExpressions.md) を使用して、前のオペレーションが成功したか失敗したかにかかわらず、再試行後も項目が正しい状態のままであることを確認します。冪等性が書き込みオペレーションの要件である場合は、[`TransactWriteItem`](transaction-apis.md#transaction-apis-txwriteitems) を使用してください。これは、同じアクションを実行する複数の試行を明確にするために自動的に `ClientRequestToken` を指定することにより、冪等リクエストをサポートします。

**ServiceUnavailable (HTTP 503)**  
DynamoDB は現在利用できません。(これは一時的な状態です。)  
再試行してもいいですか。はい

## アプリケーションのエラー処理
<a name="Programming.Errors.Handling"></a>

アプリケーションをスムーズに実行するには、エラーを見つけ、エラーに対応するロジックを組み込む必要があります。一般的な方法には、`try-catch`ブロックや`if-then`ステートメントの使用などがあります。

AWS SDK は独自に再試行とエラーチェックを実行します。AWS SDK の使用中にエラーが発生した場合は、エラーコードと説明が問題のトラブルシューティングに役立ちます。

また、レスポンスに`Request ID`が表示されます。`Request ID` は、AWS サポートを使用して問題を診断することが必要な場合に便利です。

## エラーの再試行とエクスポネンシャルバックオフ
<a name="Programming.Errors.RetryAndBackoff"></a>

特定のリクエストの処理中には、DNS サーバー、スイッチ、ロードバランサーなど、ネットワーク上のさまざまなコンポーネントが原因でエラーが発生する可能性があります。ネットワーク環境でこれらのエラー応答を処理する通常の方法は、クライアントアプリケーションで再試行を実装することです。この手法により、アプリケーションの信頼性が向上します。

各 AWS SDK は、自動的に再試行ロジックを実装しています。必要に応じて再試行パラメータを変更できます。たとえば、エラーが発生したら再試行が許可されない、Fail-Fast 方式を要求する Java アプリケーションについて考えてみましょう。AWS SDK for Java では、`ClientConfiguration` クラスを使用して `maxErrorRetry` の値を `0` に設定することで、再試行を無効にできます。詳細については、AWS SDK ドキュメントのご使用のプログラミング言語の項目を参照してください。

AWS SDK を使用していない場合は、サーバーエラー (5xx) を受け取る元のリクエストを再試行する必要があります。ただし、クライアントエラー (4xx、`ThrottlingException` または `ProvisionedThroughputExceededException` 以外) は、再試行する前にリクエスト自体を修正して問題を解決する必要があることを示しています。特定のスロットリングシナリオに対処するための詳細な推奨事項については、「[DynamoDB スロットリングのトラブルシューティング](TroubleshootingThrottling.md)」セクションを参照してください。

簡単な再試行に加えて、各 AWS SDK はエクスポネンシャルバックオフアルゴリズムを実装し、フロー制御を改善します。エクスポネンシャルバックオフは、再試行間の待機時間を累進的に長くして、連続的なエラー応答を受信するという概念に基づいています。たとえば、1 回目の再試行の前に最大 50 ミリ秒、2 回目の前に最大 100 ミリ秒、3 回目の前に最大 200 ミリ秒のようになります。ただし 1 分を経過してもリクエストが成功しない場合は、問題の原因はリクエストの速度ではなく、プロビジョニングしたスループットをリクエストのサイズが超えたためである可能性があります。1 分程度で再試行が停止するように最大回数を設定します。リクエストが失敗した場合は、プロビジョニングされたスループットのオプションを調べてください。

**注記**  
AWS SDK には自動再試行ロジックとエクスポネンシャルバックオフが実装されています。

ほとんどのエクスポネンシャルバックオフアルゴリズムは、連続した衝突を防ぐためにジッター (ランダム化された遅延) を使用します。この場合は、そうした衝突を回避しようとしていないので、乱数を使用する必要はありません。ただし、同時クライアントを使用する場合、ジッターはリクエストをより速く成功させるのに役立ちます。詳細については、「[エクスポネンシャルバックオフとジッター](http://www.awsarchitectureblog.com/2015/03/backoff.html)」に関するブログ投稿を参照してください。

## バッチオペレーションとエラー処理
<a name="Programming.Errors.BatchOperations"></a>

DynamoDB の低レベル API では、読み込み/書き込みのバッチオペレーションがサポートされています。`BatchGetItem` は 1 つ以上のテーブルからの項目の読み込みを処理し、`BatchWriteItem` は、1 つ以上のテーブルでの項目の入力や削除を処理します。これらのバッチオペレーションは、DynamoDB のバッチではない他のオペレーションのラッパーとして実装されています。つまり、`BatchGetItem` は、バッチの項目ごとに `GetItem` を一度呼び出します。同様に、`BatchWriteItem` は、`DeleteItem` または `PutItem` を必要に応じてバッチの項目ごとに呼び出します。

バッチオペレーションではバッチの個々のリクエストのエラーが許容されます。たとえば、5 つの項目を読み込む `BatchGetItem` リクエストの場合を考えます。基礎となる `GetItem` リクエストの一部が失敗した場合でも、`BatchGetItem` オペレーション全体が失敗することはありません。ただし、5 つのオペレーションにすべて失敗する場合は、`BatchGetItem` 全体が失敗します。

バッチオペレーションでは、失敗した個々のリクエストについて情報が返されるため、問題を診断し、オペレーションを再試行できます。`BatchGetItem` の場合、問題のあるテーブルとプライマリキーがレスポンスの `UnprocessedKeys` 値で返されます。`BatchWriteItem` の場合、同様の情報は `UnprocessedItems` で返されます。

読み込みまたは書き込みの失敗の原因として最も可能性が高いのは、*スロットリング*です。`BatchGetItem` の場合、バッチリクエストの 1 つ以上のテーブルに、オペレーションをサポートするための十分なプロビジョンド読み込みキャパシティーがなくなります。`BatchWriteItem` の場合、1 つ以上のテーブルに、十分なプロビジョンド書き込みキャパシティーがなくなります。

DynamoDB によって未処理の項目が返された場合は、それらの項目に対してバッチオペレーションを再試行する必要があります。ただし、*エクスポネンシャルバックオフアルゴリズムを使用することを強くお勧めします*。すぐにバッチオペレーションを再試行した場合、基礎となる読み込みまたは書き込みリクエストはやはり、個々のテーブルに対する帯域幅調整により失敗することがあります。エクスポネンシャルバックオフアルゴリズムを使用してバッチオペレーションを遅らせた場合は、バッチの個々のリクエストが成功する可能性がはるかに高くなります。

**注記**  
一部の AWS SDK では、未処理の項目の再試行を自動的に処理する高レベルのクライアントが提供されているため、この再試行ロジックを自分で実装する必要はありません。例えば、次のようになります。  
**Java** – AWS SDK for Java v2 の [DynamoDB 拡張クライアント](DynamoDBEnhanced.md)と v1 の [DynamoDBMapper](DynamoDBMapper.md) はどちらも、バッチオペレーションを実行するときに未処理の項目を自動的に再試行します。
**Python** – boto3 Table リソース `batch_writer` は、バッチ書き込みオペレーションの未処理の項目の再試行を暗黙的に処理します。詳細については、「[テーブルリソース batch\$1writer の使用](programming-with-python.md#programming-with-python-batch-writer)」を参照してください。
この動作を提供しない低レベルのクライアントまたは SDK を使用している場合は、上記のように再試行ロジックを自分で実装する必要があります。

# AWS SDK で DynamoDB を使用する
<a name="sdk-general-information-section"></a>

AWS Software Development Kit (SDK) は、多くの一般的なプログラミング言語で使用できます。各 SDK には、デベロッパーが好みの言語でアプリケーションを簡単に構築できるようになる API、コード例、およびドキュメントが提供されています。


| SDK ドキュメント | コードの例 | 
| --- | --- | 
| [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/sdk-for-cpp) | [AWS SDK for C\$1\$1 コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp) | 
| [AWS CLI](https://docs.aws.amazon.com/cli) | [AWS CLI コードの例](https://docs.aws.amazon.com/code-library/latest/ug/cli_2_code_examples.html) | 
| [AWS SDK for Go](https://docs.aws.amazon.com/sdk-for-go) | [AWS SDK for Go コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/gov2) | 
| [AWS SDK for Java](https://docs.aws.amazon.com/sdk-for-java) | [AWS SDK for Java コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2) | 
| [AWS SDK for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript) | [AWS SDK for JavaScript コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javascriptv3) | 
| [AWS SDK for Kotlin](https://docs.aws.amazon.com/sdk-for-kotlin) | [AWS SDK for Kotlin コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/kotlin) | 
| [AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net) | [AWS SDK for .NET コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3) | 
| [AWS SDK for PHP](https://docs.aws.amazon.com/sdk-for-php) | [AWS SDK for PHP コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/php) | 
| [AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell) | [AWS Tools for PowerShell コードの例](https://docs.aws.amazon.com/code-library/latest/ug/powershell_5_code_examples.html) | 
| [AWS SDK for Python (Boto3)](https://docs.aws.amazon.com/pythonsdk) | [AWS SDK for Python (Boto3) コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python) | 
| [AWS SDK for Ruby](https://docs.aws.amazon.com/sdk-for-ruby) | [AWS SDK for Ruby コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/ruby) | 
| [AWS SDK for Rust](https://docs.aws.amazon.com/sdk-for-rust) | [AWS SDK for Rust コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rustv1) | 
| [AWS SDK for SAP ABAP](https://docs.aws.amazon.com/sdk-for-sapabap) | [AWS SDK for SAP ABAP コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/sap-abap) | 
| [AWS SDK for Swift](https://docs.aws.amazon.com/sdk-for-swift) | [AWS SDK for Swift コードの例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/swift) | 

DynamoDB に固有の例については、「[AWS SDK を使用した DynamoDB のコード例](service_code_examples.md)」を参照してください。

**可用性の例**  
必要なものが見つからなかった場合。このページの下側にある [**Provide feedback**] リンクから、コードの例をリクエストしてください。