使用項目:Java - Amazon DynamoDB

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

使用項目:Java

您可以使用 AWS SDK for Java 文件API在資料表中的 Amazon DynamoDB 項目上執行一般建立、讀取、更新和刪除 (CRUD) 操作。

注意

SDK 適用於 Java 的 也提供物件持久性模型,可讓您將用戶端類別對應至 DynamoDB 資料表。此方法可以減少您必須撰寫的程式碼數量。如需詳細資訊,請參閱Java 1.x:DynamoDBMapper

本節包含執行數個 Java 文件API項目動作的 Java 範例,以及數個完整的工作範例。

放入項目

putItem 方法會將項目存放在資料表中。若已有該項目,其會取代整個項目。若不希望取代整個項目,而是只想要更新特定的屬性,可以使用 updateItem 方法。如需詳細資訊,請參閱 更新項目

Java v2
import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.services.dynamodb.model.PutItemResponse; import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; import java.util.HashMap; /** * 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 place items into an Amazon DynamoDB table using the AWS SDK for Java V2, * its better practice to use the * Enhanced Client. See the EnhancedPutItem example. */ public class PutItem { public static void main(String[] args) { final String usage = """ Usage: <tableName> <key> <keyVal> <albumtitle> <albumtitleval> <awards> <awardsval> <Songtitle> <songtitleval> Where: tableName - The Amazon DynamoDB table in which an item is placed (for example, Music3). key - The key used in the Amazon DynamoDB table (for example, Artist). keyval - The key value that represents the item to get (for example, Famous Band). albumTitle - The Album title (for example, AlbumTitle). AlbumTitleValue - The name of the album (for example, Songs About Life ). Awards - The awards column (for example, Awards). AwardVal - The value of the awards (for example, 10). SongTitle - The song title (for example, SongTitle). SongTitleVal - The value of the song title (for example, Happy Day). **Warning** This program will place an item that you specify into a table! """; if (args.length != 9) { System.out.println(usage); System.exit(1); } String tableName = args[0]; String key = args[1]; String keyVal = args[2]; String albumTitle = args[3]; String albumTitleValue = args[4]; String awards = args[5]; String awardVal = args[6]; String songTitle = args[7]; String songTitleVal = args[8]; Region region = Region.US_EAST_1; DynamoDbClient ddb = DynamoDbClient.builder() .region(region) .build(); putItemInTable(ddb, tableName, key, keyVal, albumTitle, albumTitleValue, awards, awardVal, songTitle, songTitleVal); System.out.println("Done!"); ddb.close(); } public static void putItemInTable(DynamoDbClient ddb, String tableName, String key, String keyVal, String albumTitle, String albumTitleValue, String awards, String awardVal, String songTitle, String songTitleVal) { HashMap<String, AttributeValue> itemValues = new HashMap<>(); itemValues.put(key, AttributeValue.builder().s(keyVal).build()); itemValues.put(songTitle, AttributeValue.builder().s(songTitleVal).build()); itemValues.put(albumTitle, AttributeValue.builder().s(albumTitleValue).build()); itemValues.put(awards, AttributeValue.builder().s(awardVal).build()); PutItemRequest request = PutItemRequest.builder() .tableName(tableName) .item(itemValues) .build(); try { PutItemResponse response = ddb.putItem(request); System.out.println(tableName + " was successfully updated. The request id is " + response.responseMetadata().requestId()); } catch (ResourceNotFoundException e) { System.err.format("Error: The Amazon DynamoDB table \"%s\" can't be found.\n", tableName); System.err.println("Be sure that it exists and that you've typed its name correctly!"); System.exit(1); } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } } }
Java v1

請遵循下列步驟:

  1. 建立 DynamoDB 類別的執行個體。

  2. 建立 Table 類別的執行個體,代表您要進行作業的資料表。

  3. 建立 Item 類別的執行個體,代表新的項目。您必須指定新項目的主要索引鍵及其屬性。

  4. 使用您在前述步驟中所建立的 putItem,呼叫 Table 物件的 Item 方法。

下列 Java 程式碼範例示範上述工作。程式碼會將新的項目寫入 ProductCatalog 表。

範例
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build(); DynamoDB dynamoDB = new DynamoDB(client); Table table = dynamoDB.getTable("ProductCatalog"); // Build a list of related items List<Number> relatedItems = new ArrayList<Number>(); relatedItems.add(341); relatedItems.add(472); relatedItems.add(649); //Build a map of product pictures Map<String, String> pictures = new HashMap<String, String>(); pictures.put("FrontView", "http://example.com/products/123_front.jpg"); pictures.put("RearView", "http://example.com/products/123_rear.jpg"); pictures.put("SideView", "http://example.com/products/123_left_side.jpg"); //Build a map of product reviews Map<String, List<String>> reviews = new HashMap<String, List<String>>(); List<String> fiveStarReviews = new ArrayList<String>(); fiveStarReviews.add("Excellent! Can't recommend it highly enough! Buy it!"); fiveStarReviews.add("Do yourself a favor and buy this"); reviews.put("FiveStar", fiveStarReviews); List<String> oneStarReviews = new ArrayList<String>(); oneStarReviews.add("Terrible product! Do not buy this."); reviews.put("OneStar", oneStarReviews); // Build the item Item item = new Item() .withPrimaryKey("Id", 123) .withString("Title", "Bicycle 123") .withString("Description", "123 description") .withString("BicycleType", "Hybrid") .withString("Brand", "Brand-Company C") .withNumber("Price", 500) .withStringSet("Color", new HashSet<String>(Arrays.asList("Red", "Black"))) .withString("ProductCategory", "Bicycle") .withBoolean("InStock", true) .withNull("QuantityOnHand") .withList("RelatedItems", relatedItems) .withMap("Pictures", pictures) .withMap("Reviews", reviews); // Write the item to the table PutItemOutcome outcome = table.putItem(item);

在前述範例中,項目具有的屬性為純量 (StringNumberBooleanNull)、集合 (String Set) 及文件類型 (ListMap)。

指定選用參數

除了必要的參數之外,您也可為 putItem 方法指定選用的參數。例如,下列 Java 程式碼範例會使用選用參數來指定上傳項目的條件。如果您指定的條件不符合, 會 AWS SDK for Java 擲回 ConditionalCheckFailedException。程式碼範例在 putItem 方法中指定了下列選用參數:

  • ConditionExpression 會定義要求的條件。只有當具有等於特定值的ISBN屬性時,程式碼才會定義取代具有相同主索引鍵的現有項目的條件。

  • 用於條件中的 ExpressionAttributeValues 映射。在此情況下,只需要一個取代:條件表達:val式中的預留位置會在執行期替換為要檢查的ISBN實際值。

下列範例會使用這些選用參數,新增新的書籍項目。

範例
Item item = new Item() .withPrimaryKey("Id", 104) .withString("Title", "Book 104 Title") .withString("ISBN", "444-4444444444") .withNumber("Price", 20) .withStringSet("Authors", new HashSet<String>(Arrays.asList("Author1", "Author2"))); Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); expressionAttributeValues.put(":val", "444-4444444444"); PutItemOutcome outcome = table.putItem( item, "ISBN = :val", // ConditionExpression parameter null, // ExpressionAttributeNames parameter - we're not using it for this example expressionAttributeValues);

PutItem 和 JSON 文件

您可以在 DynamoDB 資料表中將JSON文件儲存為屬性。若要執行此作業,請使用 ItemwithJSON 方法。此方法剖析JSON文件,並將每個元素對應至原生 DynamoDB 資料類型。

假設您想要存放下列JSON文件,其中包含可履行特定產品訂單的供應商。

範例
{ "V01": { "Name": "Acme Books", "Offices": [ "Seattle" ] }, "V02": { "Name": "New Publishers, Inc.", "Offices": ["London", "New York" ] }, "V03": { "Name": "Better Buy Books", "Offices": [ "Tokyo", "Los Angeles", "Sydney" ] } }

您可以使用 withJSON 方法,將此存放在 ProductCatalog 表,放在名為 VendorInfoMap 屬性中。下列 Java 程式碼範例會示範如何執行此作業。

// Convert the document into a String. Must escape all double-quotes. String vendorDocument = "{" + " \"V01\": {" + " \"Name\": \"Acme Books\"," + " \"Offices\": [ \"Seattle\" ]" + " }," + " \"V02\": {" + " \"Name\": \"New Publishers, Inc.\"," + " \"Offices\": [ \"London\", \"New York\"" + "]" + "}," + " \"V03\": {" + " \"Name\": \"Better Buy Books\"," + "\"Offices\": [ \"Tokyo\", \"Los Angeles\", \"Sydney\"" + " ]" + " }" + " }"; Item item = new Item() .withPrimaryKey("Id", 210) .withString("Title", "Book 210 Title") .withString("ISBN", "210-2102102102") .withNumber("Price", 30) .withJSON("VendorInfo", vendorDocument); PutItemOutcome outcome = table.putItem(item);

取得項目

若要擷取單一項目,請使用 getItem 物件的 Table 方法。請遵循下列步驟:

  1. 建立 DynamoDB 類別的執行個體。

  2. 建立 Table 類別的執行個體,代表您要進行作業的資料表。

  3. 呼叫 getItem 執行個體的 Table 方法。您必須指定希望擷取之項目的主要索引鍵。

下列 Java 程式碼範例示範上述步驟。程式碼會取得具有指定分割區索引鍵的項目。

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build(); DynamoDB dynamoDB = new DynamoDB(client); Table table = dynamoDB.getTable("ProductCatalog"); Item item = table.getItem("Id", 210);

指定選用參數

除了必要的參數之外,您也可為 getItem 方法指定選用的參數。例如,下列 Java 程式碼範例使用選用方法,只擷取特定的屬性清單,以及指定強烈一致讀取。(若要進一步了解讀取一致性,請參閱「DynamoDB 讀取一致性」。)

您可以使用 ProjectionExpression,只擷取特定的屬性或元素,而非整個項目。ProjectionExpression 可以使用文件路徑,指定最上層或巢狀屬性。如需詳細資訊,請參閱 在 DynamoDB 中使用投影表達式

getItem 方法的參數不會讓您指定讀取一致性。但您可以建立 GetItemSpec,它會提供低階 GetItem 操作輸入的完整存取。以下程式碼範例會建立 GetItemSpec,然後使用該規格做為 getItem 方法的輸入。

範例
GetItemSpec spec = new GetItemSpec() .withPrimaryKey("Id", 206) .withProjectionExpression("Id, Title, RelatedItems[0], Reviews.FiveStar") .withConsistentRead(true); Item item = table.getItem(spec); System.out.println(item.toJSONPretty());

若要將 Item 以可供人閱讀的格式印出,請使用 toJSONPretty 方法。上個範例的輸出類似這樣。

{ "RelatedItems" : [ 341 ], "Reviews" : { "FiveStar" : [ "Excellent! Can't recommend it highly enough! Buy it!", "Do yourself a favor and buy this" ] }, "Id" : 123, "Title" : "20-Bicycle 123" }

GetItem 和 JSON 文件

PutItem 和 JSON 文件區段中,您將JSON文件存放在名為 的Map屬性中VendorInfo。您可以使用 getItem方法,以 JSON 格式擷取整個文件。或者可以使用文件路徑標記法擷取文件中的部分元素。下列 Java 程式碼範例會示範這些技術。

GetItemSpec spec = new GetItemSpec() .withPrimaryKey("Id", 210); System.out.println("All vendor info:"); spec.withProjectionExpression("VendorInfo"); System.out.println(table.getItem(spec).toJSON()); System.out.println("A single vendor:"); spec.withProjectionExpression("VendorInfo.V03"); System.out.println(table.getItem(spec).toJSON()); System.out.println("First office location for this vendor:"); spec.withProjectionExpression("VendorInfo.V03.Offices[0]"); System.out.println(table.getItem(spec).toJSON());

上個範例的輸出類似這樣。

All vendor info: {"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]},"V02":{"Name":"New Publishers, Inc.","Offices":["London","New York"]},"V01":{"Name":"Acme Books","Offices":["Seattle"]}}} A single vendor: {"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]}}} First office location for a single vendor: {"VendorInfo":{"V03":{"Offices":["Tokyo"]}}}
注意

您可以使用 toJSON方法將任何項目 (或其屬性) 轉換為 JSON格式化字串。下列程式碼會擷取數個頂層和巢狀屬性,並將結果列印為 JSON。

GetItemSpec spec = new GetItemSpec() .withPrimaryKey("Id", 210) .withProjectionExpression("VendorInfo.V01, Title, Price"); Item item = table.getItem(spec); System.out.println(item.toJSON());

輸出看起來如下。

{"VendorInfo":{"V01":{"Name":"Acme Books","Offices":["Seattle"]}},"Price":30,"Title":"Book 210 Title"}

批次寫入:放入和刪除多個項目

批次寫入表示在一個批次中放入和刪除多個項目。您可利用 batchWriteItem 方法,在單一呼叫中對來自一或多個資料表的多個項目執行放入與刪除操作。以下是使用 AWS SDK for Java 文件 放置或刪除多個項目的步驟API。

  1. 建立 DynamoDB 類別的執行個體。

  2. 建立 TableWriteItems 類別的執行個體,其描述針對資料表所有的寫入與刪除操作。若希望用單一批次寫入操作寫入多份資料表,您必須每份資料表都建立一個 TableWriteItems 執行個體。

  3. 提供您在前述步驟中建立的 batchWriteItem 物件,藉以呼叫 TableWriteItems 方法。

  4. 處理回應。您應該檢查回應中是否傳回任何未經處理的請求項目。如果您達到佈建輸送量配額或遇到一些其他暫時性錯誤,就可能發生這個狀況。此外,DynamoDB 會限制您在請求中指定的請求大小及操作次數。如果您超出這些限制,DynamoDB 會拒絕此請求。如需詳細資訊,請參閱Amazon DynamoDB 中的服務、帳戶和資料表配額

下列 Java 程式碼範例示範上述步驟。範例會在兩份資料表上執行 batchWriteItem 操作:ForumThread。對應的 TableWriteItems 物件會定義下列動作:

  • Forum 表中放入一個項目。

  • Thread 表中寫入及刪除一個項目。

該程式碼接著會呼叫 batchWriteItem 來執行操作。

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build(); DynamoDB dynamoDB = new DynamoDB(client); TableWriteItems forumTableWriteItems = new TableWriteItems("Forum") .withItemsToPut( new Item() .withPrimaryKey("Name", "Amazon RDS") .withNumber("Threads", 0)); TableWriteItems threadTableWriteItems = new TableWriteItems("Thread") .withItemsToPut( new Item() .withPrimaryKey("ForumName","Amazon RDS","Subject","Amazon RDS Thread 1") .withHashAndRangeKeysToDelete("ForumName","Some partition key value", "Amazon S3", "Some sort key value"); BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems, threadTableWriteItems); // Code for checking unprocessed items is omitted in this example

如需運作範例,請參閱 範例:使用 AWS SDK for Java 文件的批次寫入操作 API

批次取得:取得多個項目

您可利用 batchGetItem 方法,從一或多個資料表擷取多個項目。若要擷取單一項目,可以使用 getItem 方法。

請遵循下列步驟:

  1. 建立 DynamoDB 類別的執行個體。

  2. 建立 TableKeysAndAttributes 類別的執行個體,其描述要從資料表擷取的主要索引鍵值清單。若希望用單一批次擷取操作讀取多份資料表,您必須每份資料表都建立一個 TableKeysAndAttributes 執行個體。

  3. 提供您在前述步驟中建立的 batchGetItem 物件,藉以呼叫 TableKeysAndAttributes 方法。

下列 Java 程式碼範例示範上述步驟。本範例會從 Forum 表擷取兩個項目,從 Thread 表擷取三個項目。

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build(); DynamoDB dynamoDB = new DynamoDB(client); TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes(forumTableName); forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon DynamoDB"); TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes(threadTableName); threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject", "Amazon DynamoDB","DynamoDB Thread 1", "Amazon DynamoDB","DynamoDB Thread 2", "Amazon S3","S3 Thread 1"); BatchGetItemOutcome outcome = dynamoDB.batchGetItem( forumTableKeysAndAttributes, threadTableKeysAndAttributes); for (String tableName : outcome.getTableItems().keySet()) { System.out.println("Items in table " + tableName); List<Item> items = outcome.getTableItems().get(tableName); for (Item item : items) { System.out.println(item); } }

指定選用參數

除了必要的參數之外,您也可在使用 batchGetItem 時指定選用的參數。例如,您可為每個定義的 ProjectionExpression 提供 TableKeysAndAttributes。您如此即可指定要從資料表擷取的屬性。

下列程式碼範例會從 Forum 表擷取兩個項目。withProjectionExpression 參數會指定只擷取 Threads 屬性。

範例
TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes("Forum") .withProjectionExpression("Threads"); forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon DynamoDB"); BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes);

更新項目

updateItem 物件的 Table 方法可更新現有的屬性值、新增新的屬性,或是從現有項目中刪除屬性。

updateItem 方法的行為如下:

  • 若某項目不存在 (資料表中沒有具備指定主索引鍵的項目),則 updateItem 會在資料表中新增一個新項目。

  • 若項目存在,updateItem 會依 UpdateExpression 參數的指定,執行更新。

注意

您也可以使用 putItem 來「更新」項目。例如,若呼叫 putItem 將項目新增至資料表,但具備指定主索引鍵的項目已存在,則 putItem 會取代整個項目。如果輸入內並未指定現有項目中的屬性,putItem 就會從項目中移除這些屬性。

一般而言,建議您在想要修改任何項目屬性時,使用 updateItemupdateItem 方法只會修改您在輸入內指定的項目屬性,而項目內的其他屬性則保持不變。

請遵循下列步驟:

  1. 建立 Table 類別的執行個體,代表您要使用的資料表。

  2. 呼叫 updateTable 執行個體的 Table 方法。您必須指定要擷取之項目的主要索引鍵,以及描述要修改之屬性及修改方式的 UpdateExpression

下列 Java 程式碼範例示範上述工作。程式碼會更新 ProductCatalog 表中的書籍項目。其會將新的作者新增到 Authors 集合中,並刪除現有的 ISBN 屬性。它也會將價格減一。

ExpressionAttributeValues 映射內容會用於 UpdateExpression 中。預留位置 :val1:val2,會於執行時間由 AuthorsPrice 的實際值取代。

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build(); DynamoDB dynamoDB = new DynamoDB(client); Table table = dynamoDB.getTable("ProductCatalog"); Map<String, String> expressionAttributeNames = new HashMap<String, String>(); expressionAttributeNames.put("#A", "Authors"); expressionAttributeNames.put("#P", "Price"); expressionAttributeNames.put("#I", "ISBN"); Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); expressionAttributeValues.put(":val1", new HashSet<String>(Arrays.asList("Author YY","Author ZZ"))); expressionAttributeValues.put(":val2", 1); //Price UpdateItemOutcome outcome = table.updateItem( "Id", // key attribute name 101, // key attribute value "add #A :val1 set #P = #P - :val2 remove #I", // UpdateExpression expressionAttributeNames, expressionAttributeValues);

指定選用參數

除了必要的參數之外,您也可以為 updateItem 方法指定選用參數,包括必須滿足才會發生更新的條件。如果您指定的條件不符合, 會 AWS SDK for Java 擲回 ConditionalCheckFailedException。例如,下列 Java 程式碼範例會依據條件,將書籍項目的價格更新為 25。其會指定 ConditionExpression,指出只有在現有價格為 20 時才更新價格。

範例
Table table = dynamoDB.getTable("ProductCatalog"); Map<String, String> expressionAttributeNames = new HashMap<String, String>(); expressionAttributeNames.put("#P", "Price"); Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); expressionAttributeValues.put(":val1", 25); // update Price to 25... expressionAttributeValues.put(":val2", 20); //...but only if existing Price is 20 UpdateItemOutcome outcome = table.updateItem( new PrimaryKey("Id",101), "set #P = :val1", // UpdateExpression "#P = :val2", // ConditionExpression expressionAttributeNames, expressionAttributeValues);

原子計數器

您可以使用 updateItem 來實作原子計數器以增加或減少現有屬性的值,卻不干擾其他寫入請求。若要增加原子計數器,請於使用 UpdateExpression 時搭配 set 動作,將數值新增到類型為 Number 的現有屬性。

下列範例示範這項作業,將 Quantity 屬性加 1。其也同時示範在 ExpressionAttributeNames 中使用 UpdateExpression 參數。

Table table = dynamoDB.getTable("ProductCatalog"); Map<String,String> expressionAttributeNames = new HashMap<String,String>(); expressionAttributeNames.put("#p", "PageCount"); Map<String,Object> expressionAttributeValues = new HashMap<String,Object>(); expressionAttributeValues.put(":val", 1); UpdateItemOutcome outcome = table.updateItem( "Id", 121, "set #p = #p + :val", expressionAttributeNames, expressionAttributeValues);

刪除項目

deleteItem 方法會從資料表刪除項目。您必須提供要刪除項目的主索引鍵。

請遵循下列步驟:

  1. 建立 DynamoDB 用戶端執行個體。

  2. 提供希望刪除之項目的索引鍵,可呼叫 deleteItem 方法。

下列 Java 範例示範這些任務。

範例
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build(); DynamoDB dynamoDB = new DynamoDB(client); Table table = dynamoDB.getTable("ProductCatalog"); DeleteItemOutcome outcome = table.deleteItem("Id", 101);

指定選用參數

您可以為 deleteItem 指定選用參數。例如,下列 Java 程式碼範例指定 ConditionExpression,指出只有當書籍不再出版時 (InPublication 屬性為 false),才能刪除 ProductCatalog 中的書籍項目。

範例
Map<String,Object> expressionAttributeValues = new HashMap<String,Object>(); expressionAttributeValues.put(":val", false); DeleteItemOutcome outcome = table.deleteItem("Id",103, "InPublication = :val", null, // ExpressionAttributeNames - not used in this example expressionAttributeValues);