

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

# 搭配適用於 Java 1.x 的 AWS 開發套件使用 DAX
<a name="DAX.client.java-sdk-v1"></a>

請按照此程序操作，在 Amazon EC2 執行個體上執行 Amazon DynamoDB Accelerator (DAX) 的 Java 範例。

**注意**  
這些說明是針對使用適用於 Java 1.x 的 AWS 軟體開發套件的應用程式。如需使用適用於 Java 2.x 的 AWS 軟體開發套件的應用程式，請參閱 [Java 與 DAX](DAX.client.run-application-java.md)。

**執行 DAX 的 Java 範例**

1. 安裝 Java 開發套件 (JDK)。

   ```
   sudo yum install -y java-devel
   ```

1. 下載 適用於 Java 的 AWS SDK (`.zip` 檔案)，並將其解壓縮。

   ```
   wget http://sdk-for-java.amazonwebservices.com/latest/aws-java-sdk.zip
   
   unzip aws-java-sdk.zip
   ```

1. 下載 DAX Java 用戶端 (`.jar` 檔) 最新版本。

   ```
   wget http://dax-sdk.s3-website-us-west-2.amazonaws.com/java/DaxJavaClient-latest.jar
   ```
**注意**  
DAX SDK for Java 用戶端可在 Apache Maven 上取得。如需詳細資訊，請參閱 [使用用戶端做為 Apache Maven 依存項目](#DAXClient.Maven)。

1. 設定您的 `CLASSPATH` 變數。在此範例中，將 `sdkVersion` 取代為 適用於 Java 的 AWS SDK 的實際版本號碼 (例如 `1.11.112`)。

   ```
   export SDKVERSION=sdkVersion
   
   export CLASSPATH=$(pwd)/TryDax/java:$(pwd)/DaxJavaClient-latest.jar:$(pwd)/aws-java-sdk-$SDKVERSION/lib/aws-java-sdk-$SDKVERSION.jar:$(pwd)/aws-java-sdk-$SDKVERSION/third-party/lib/*
   ```

1. 下載範例程式來源碼 (`.zip` 檔案)。

   ```
   wget http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/samples/TryDax.zip
   ```

   下載完成後，解壓縮來源檔案。

   ```
   unzip TryDax.zip
   ```

1. 前往 Java 程式碼目錄並編譯程式碼，如下所示。

   ```
   cd TryDax/java/
   javac TryDax*.java
   ```

1. 執行程式。

   ```
   java TryDax
   ```

   您應該會看到類似下列的輸出。

   ```
   Creating a DynamoDB client
   
   Attempting to create table; please wait...
   Successfully created table.  Table status: ACTIVE
   Writing data to the table...
   Writing 10 items for partition key: 1
   Writing 10 items for partition key: 2
   Writing 10 items for partition key: 3
   Writing 10 items for partition key: 4
   Writing 10 items for partition key: 5
   Writing 10 items for partition key: 6
   Writing 10 items for partition key: 7
   Writing 10 items for partition key: 8
   Writing 10 items for partition key: 9
   Writing 10 items for partition key: 10
   
   Running GetItem, Scan, and Query tests...
   First iteration of each test will result in cache misses
   Next iterations are cache hits
   
   GetItem test - partition key 1 and sort keys 1-10
   	Total time: 136.681 ms - Avg time: 13.668 ms
   	Total time: 122.632 ms - Avg time: 12.263 ms
   	Total time: 167.762 ms - Avg time: 16.776 ms
   	Total time: 108.130 ms - Avg time: 10.813 ms
   	Total time: 137.890 ms - Avg time: 13.789 ms
   Query test - partition key 5 and sort keys between 2 and 9
   	Total time: 13.560 ms - Avg time: 2.712 ms
   	Total time: 11.339 ms - Avg time: 2.268 ms
   	Total time: 7.809 ms - Avg time: 1.562 ms
   	Total time: 10.736 ms - Avg time: 2.147 ms
   	Total time: 12.122 ms - Avg time: 2.424 ms
   Scan test - all items in the table
   	Total time: 58.952 ms - Avg time: 11.790 ms
   	Total time: 25.507 ms - Avg time: 5.101 ms
   	Total time: 37.660 ms - Avg time: 7.532 ms
   	Total time: 26.781 ms - Avg time: 5.356 ms
   	Total time: 46.076 ms - Avg time: 9.215 ms
   
   Attempting to delete table; please wait...
   Successfully deleted table.
   ```

   記下計時資訊：`GetItem`、`Query` 和 `Scan` 測試所需要的毫秒數。

1. 在先前的步驟中，您已針對 DynamoDB 端點執行程式。現在，請再次執行程式，但這一次 `GetItem`、`Query` 和 `Scan` 操作會由您的 DAX 叢集處理。

   若要判斷您 DAX 叢集的端點，請選擇下列其中一個項目：
   + **使用 DynamoDB 主控台**：選擇您的 DAX 叢集。叢集端點會在主控台上顯示，如以下範例。

     ```
     dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
     ```
   + **使用 AWS CLI**：輸入下列命令。

     ```
     aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
     ```

     如下列範例所示，叢集端點會在輸出上顯示。

     ```
     {
         "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
         "Port": 8111,
         "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
     }
     ```

   現在重新執行程式，但這一次，請將叢集端點做為命令列參數指定。

   ```
   java TryDax dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   ```

   查看輸出的剩餘部分，並記下計時資訊。使用 DAX 的 `GetItem`、`Query` 和 `Scan` 已耗用時間應遠低於使用 DynamoDB 的已耗用時間。

如需此程式的詳細資訊，請參閱下列各節：
+ [TryDax.java](DAX.client.run-application-java.TryDax.md)
+ [TryDaxHelper.java](DAX.client.run-application-java.TryDaxHelper.md)
+ [TryDaxTests.java](DAX.client.run-application-java.TryDaxTests.md)

## 使用用戶端做為 Apache Maven 依存項目
<a name="DAXClient.Maven"></a>

遵循這些步驟，在您的應用程式中將 DAX SDK for Java 用戶端做為依存項目使用。

**使用用戶端作為 Maven 依存項目**

1. 下載並安裝 Apache Maven。如需詳細資訊，請參閱[下載 Apache Maven](https://maven.apache.org/download.cgi) 和[安裝 Apache Maven](https://maven.apache.org/install.html)。

1. 將用戶端 Maven 依存項目新增至您應用程式的專案物件模型 (POM) 檔案。在此範例中，將 `x.x.x.x` 取代為用戶端的實際版本號碼 (例如 `1.0.200704.0`)。

   ```
   <!--Dependency:-->
   <dependencies>
       <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>amazon-dax-client</artifactId>
        <version>x.x.x.x</version>
       </dependency>
   </dependencies>
   ```

# TryDax.java
<a name="DAX.client.run-application-java.TryDax"></a>

`TryDax.java` 檔案包含 `main` 方法。若您不使用任何命令列參數執行程式，它會建立 Amazon DynamoDB 用戶端，並使用該用戶端進行所有 API 操作。若您在命令列指定 DynamoDB Accelerator (DAX) 叢集端點，程式也會建立 DAX 用戶端，並用它來進行 `GetItem`、`Query` 和 `Scan` 操作。

您可以使用幾種方法修改程式：
+ 使用 DAX 用戶端，而非 DynamoDB 用戶端。如需詳細資訊，請參閱 [Java 與 DAX](DAX.client.run-application-java.md)。
+ 為測試資料表選擇不同的名稱。
+ 變更 `helper.writeData` 參數，修改寫入的項目數目。第二個參數是分割區索引鍵的數字，第三個參數則為排序索引鍵的數字。根據預設，程式會使用 1-10 作為分割區索引鍵的值，使用 1-10 作為排序索引鍵的值，總共會將 100 個項目寫入資料表。如需詳細資訊，請參閱 [TryDaxHelper.java](DAX.client.run-application-java.TryDaxHelper.md)。
+ 修改 `GetItem`、`Query` 和 `Scan` 測試的數字，並修改其參數。
+ 將包含 `helper.createTable` 和 `helper.deleteTable` 的行變更為註解 (若您不希望每次執行程式時都建立和刪除資料表的話)。

**注意**  
若要執行此程式，您可以設定 Maven 將適用於 Java 的 DAX 軟體開發套件的用戶端與 適用於 Java 的 AWS SDK 用作依存項目。如需詳細資訊，請參閱 [使用用戶端做為 Apache Maven 依存項目](DAX.client.java-sdk-v1.md#DAXClient.Maven)。  
或者，您必須在 classpath 中同時下載和包含 DAX Java 用戶端及 適用於 Java 的 AWS SDK。請參閱 [Java 與 DAX](DAX.client.run-application-java.md) 以取得設定您 `CLASSPATH` 變數的範例。

```
public class TryDax {

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

        TryDaxHelper helper = new TryDaxHelper();
        TryDaxTests tests = new TryDaxTests();

        DynamoDB ddbClient = helper.getDynamoDBClient();
        DynamoDB daxClient = null;
        if (args.length >= 1) {
            daxClient = helper.getDaxClient(args[0]);
        }

        String tableName = "TryDaxTable";

        System.out.println("Creating table...");
        helper.createTable(tableName, ddbClient);
        System.out.println("Populating table...");
        helper.writeData(tableName, ddbClient, 10, 10);

        DynamoDB testClient = null;
        if (daxClient != null) {
            testClient = daxClient;
        } else {
            testClient = ddbClient;
        }

        System.out.println("Running GetItem, Scan, and Query tests...");
        System.out.println("First iteration of each test will result in cache misses");
        System.out.println("Next iterations are cache hits\n");

        // GetItem
        tests.getItemTest(tableName, testClient, 1, 10, 5);

        // Query
        tests.queryTest(tableName, testClient, 5, 2, 9, 5);

        // Scan
        tests.scanTest(tableName, testClient, 5);

        helper.deleteTable(tableName, ddbClient);
    }

}
```

# TryDaxHelper.java
<a name="DAX.client.run-application-java.TryDaxHelper"></a>

`TryDaxHelper.java` 檔案包含公用程式方法。

`getDynamoDBClient` 和 `getDaxClient` 方法提供 Amazon DynamoDB 和 DynamoDB Accelerator (DAX) 用戶端。針對控制平面操作 (`CreateTable`、`DeleteTable`) 及寫入操作，程式會使用 DynamoDB 用戶端。若您指定 DAX 叢集端點，主程式會建立 DAX 用戶端來執行讀取操作 (`GetItem`、`Query`、`Scan`)。

其他 `TryDaxHelper` 方法 (`createTable`、`writeData`、`deleteTable`) 用於設定及卸除 DynamoDB 資料表和其資料。

您可以使用幾種方法修改程式：
+ 針對資料表使用不同的佈建輸送量設定。
+ 修改每個寫入項目的大小 (請參閱 `stringSize` 方法中的 `writeData` 變數)。
+ 修改 `GetItem`、`Query` 和 `Scan` 測試的數字及其參數。
+ 將包含 `helper.CreateTable` 和 `helper.DeleteTable` 的行變更為註解 (若您不希望每次執行程式時都建立和刪除資料表的話)。

**注意**  
 若要執行此程式，您可以設定 Maven 將適用於 Java 的 DAX 軟體開發套件的用戶端與 適用於 Java 的 AWS SDK 用作依存項目。如需詳細資訊，請參閱 [使用用戶端做為 Apache Maven 依存項目](DAX.client.java-sdk-v1.md#DAXClient.Maven)。  
或者，您必須在 classpath 中同時下載和包含 DAX Java 用戶端及 適用於 Java 的 AWS SDK。請參閱 [Java 與 DAX](DAX.client.run-application-java.md) 以取得設定您 `CLASSPATH` 變數的範例。

```
import com.amazon.dax.client.dynamodbv2.AmazonDaxClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.util.EC2MetadataUtils;

public class TryDaxHelper {

    private static final String region = EC2MetadataUtils.getEC2InstanceRegion();

    DynamoDB getDynamoDBClient() {
        System.out.println("Creating a DynamoDB client");
        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
                .withRegion(region)
                .build();
        return new DynamoDB(client);
    }

    DynamoDB getDaxClient(String daxEndpoint) {
        System.out.println("Creating a DAX client with cluster endpoint " + daxEndpoint);
        AmazonDaxClientBuilder daxClientBuilder = AmazonDaxClientBuilder.standard();
        daxClientBuilder.withRegion(region).withEndpointConfiguration(daxEndpoint);
        AmazonDynamoDB client = daxClientBuilder.build();
        return new DynamoDB(client);
    }

    void createTable(String tableName, DynamoDB client) {
        Table table = client.getTable(tableName);
        try {
            System.out.println("Attempting to create table; please wait...");

            table = client.createTable(tableName,
                    Arrays.asList(
                            new KeySchemaElement("pk", KeyType.HASH), // Partition key
                            new KeySchemaElement("sk", KeyType.RANGE)), // Sort key
                    Arrays.asList(
                            new AttributeDefinition("pk", ScalarAttributeType.N),
                            new AttributeDefinition("sk", ScalarAttributeType.N)),
                    new ProvisionedThroughput(10L, 10L));
            table.waitForActive();
            System.out.println("Successfully created table.  Table status: " +
                    table.getDescription().getTableStatus());

        } catch (Exception e) {
            System.err.println("Unable to create table: ");
            e.printStackTrace();
        }
    }

    void writeData(String tableName, DynamoDB client, int pkmax, int skmax) {
        Table table = client.getTable(tableName);
        System.out.println("Writing data to the table...");

        int stringSize = 1000;
        StringBuilder sb = new StringBuilder(stringSize);
        for (int i = 0; i < stringSize; i++) {
            sb.append('X');
        }
        String someData = sb.toString();

        try {
            for (Integer ipk = 1; ipk <= pkmax; ipk++) {
                System.out.println(("Writing " + skmax + " items for partition key: " + ipk));
                for (Integer isk = 1; isk <= skmax; isk++) {
                    table.putItem(new Item()
                            .withPrimaryKey("pk", ipk, "sk", isk)
                            .withString("someData", someData));
                }
            }
        } catch (Exception e) {
            System.err.println("Unable to write item:");
            e.printStackTrace();
        }
    }

    void deleteTable(String tableName, DynamoDB client) {
        Table table = client.getTable(tableName);
        try {
            System.out.println("\nAttempting to delete table; please wait...");
            table.delete();
            table.waitForDelete();
            System.out.println("Successfully deleted table.");

        } catch (Exception e) {
            System.err.println("Unable to delete table: ");
            e.printStackTrace();
        }
    }

}
```

# TryDaxTests.java
<a name="DAX.client.run-application-java.TryDaxTests"></a>

`TryDaxTests.java` 檔案包含對 Amazon DynamoDB 中測試資料表執行讀取操作的方法。這些方法皆未考慮其存取資料的方法 (使用 DynamoDB 用戶端或 DAX 用戶端)，因此不需修改應用程式邏輯。

您可以使用幾種方法修改程式：
+ 修改 `queryTest` 方法，使其使用不同的 `KeyConditionExpression`。
+ 將 `ScanFilter` 新增至 `scanTest` 方法，使其只傳回一部分的項目。

**注意**  
 若要執行此程式，您可以設定 Maven 將適用於 Java 的 DAX 軟體開發套件的用戶端與 適用於 Java 的 AWS SDK 用作依存項目。如需詳細資訊，請參閱 [使用用戶端做為 Apache Maven 依存項目](DAX.client.java-sdk-v1.md#DAXClient.Maven)。  
或者，您必須在 classpath 中同時下載和包含 DAX Java 用戶端及 適用於 Java 的 AWS SDK。請參閱 [Java 與 DAX](DAX.client.run-application-java.md) 以取得設定您 `CLASSPATH` 變數的範例。

```
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;

public class TryDaxTests {

    void getItemTest(String tableName, DynamoDB client, int pk, int sk, int iterations) {
        long startTime, endTime;
        System.out.println("GetItem test - partition key " + pk + " and sort keys 1-" + sk);
        Table table = client.getTable(tableName);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            try {
                for (Integer ipk = 1; ipk <= pk; ipk++) {
                    for (Integer isk = 1; isk <= sk; isk++) {
                        table.getItem("pk", ipk, "sk", isk);
                    }
                }
            } catch (Exception e) {
                System.err.println("Unable to get item:");
                e.printStackTrace();
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, pk * sk);
        }
    }

    void queryTest(String tableName, DynamoDB client, int pk, int sk1, int sk2, int iterations) {
        long startTime, endTime;
        System.out.println("Query test - partition key " + pk + " and sort keys between " + sk1 + " and " + sk2);
        Table table = client.getTable(tableName);

        HashMap<String, Object> valueMap = new HashMap<String, Object>();
        valueMap.put(":pkval", pk);
        valueMap.put(":skval1", sk1);
        valueMap.put(":skval2", sk2);

        QuerySpec spec = new QuerySpec()
                .withKeyConditionExpression("pk = :pkval and sk between :skval1 and :skval2")
                .withValueMap(valueMap);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            ItemCollection<QueryOutcome> items = table.query(spec);

            try {
                Iterator<Item> iter = items.iterator();
                while (iter.hasNext()) {
                    iter.next();
                }
            } catch (Exception e) {
                System.err.println("Unable to query table:");
                e.printStackTrace();
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, iterations);
        }
    }

    void scanTest(String tableName, DynamoDB client, int iterations) {
        long startTime, endTime;
        System.out.println("Scan test - all items in the table");
        Table table = client.getTable(tableName);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            ItemCollection<ScanOutcome> items = table.scan();
            try {

                Iterator<Item> iter = items.iterator();
                while (iter.hasNext()) {
                    iter.next();
                }
            } catch (Exception e) {
                System.err.println("Unable to scan table:");
                e.printStackTrace();
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, iterations);
        }
    }

    public void printTime(long startTime, long endTime, int iterations) {
        System.out.format("\tTotal time: %.3f ms - ", (endTime - startTime) / (1000000.0));
        System.out.format("Avg time: %.3f ms\n", (endTime - startTime) / (iterations * 1000000.0));
    }
}
```