Trabalhar com itens: Java - Amazon DynamoDB

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Trabalhar com itens: Java

Você pode usar a API de documentos do AWS SDK for Java para realizar operações create, read, update e delete (CRUD) típicas nos itens do Amazon DynamoDB em uma tabela.

nota

O SDK for Java também fornece um modelo de persistência de objetos que permite que você mapeie suas classes do lado do cliente para tabelas do DynamoDB. Essa abordagem pode reduzir a quantidade de código que você precisa escrever. Para ter mais informações, consulte Java 1.x: DynamoDBMapper.

Esta seção contém exemplos de Java para executar várias ações de itens da API de documento do Java e vários exemplos funcionais completos.

Colocar um item

O método putItem armazena um item em uma tabela. Se o item existe, ele substitui o item inteiro. Em vez de substituir o item inteiro, se você quiser atualizar apenas atributos específicos, use o método updateItem. Para ter mais informações, consulte Atualizar um item.

Siga estas etapas:

  1. Crie uma instância da classe DynamoDB.

  2. Crie uma instância da classe Table para representar a tabela com a qual você deseja trabalhar.

  3. Crie uma instância da classe Item para representar o novo item. Você deve especificar a chave primária do novo item e seus atributos.

  4. Chame o método putItem do objeto Table, usando o Item que você criou na etapa anterior.

O exemplo de código Java a seguir demonstra as tarefas anteriores. O código grava um novo item na tabela ProductCatalog.

exemplo
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);

No exemplo anterior, o item tem atributos que são escalares (String, Number, Boolean, Null), conjuntos (String Set) e tipos de documento (List, Map).

Especificar parâmetros opcionais

Além dos parâmetros obrigatórios, você também pode especificar parâmetros opcionais para o método putItem. Por exemplo, o seguinte exemplo de código Java usa um parâmetro opcional para especificar uma condição para fazer upload do item. Se a condição que você especificar não for atendida, o AWS SDK for Java lançará uma ConditionalCheckFailedException. O exemplo de código especifica os seguintes parâmetros opcionais no método putItem:

  • Uma ConditionExpression que define as condições para a solicitação. O código define a condição de que o item existente com a mesma chave primária será substituído somente se tiver um atributo ISBN igual a um valor específico.

  • Um mapa para ExpressionAttributeValues que é usado na condição. Nesse caso, existe apenas uma substituição obrigatória: o espaço reservado :val na expressão de condição é substituído em tempo de execução pelo valor de ISBN real a ser verificado.

O exemplo a seguir adiciona um novo item de livro usando esses parâmetros opcionais.

exemplo
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 e documentos JSON

Você pode armazenar um documento JSON como um atributo em uma tabela do DynamoDB. Para fazer isso, use o método withJSON de Item. Esse método analisa o documento JSON e mapeia cada elemento em um tipo de dados nativo do DynamoDB.

Suponha que você quisesse armazenar o seguinte documento JSON que contém os fornecedores que podem atender a pedidos de um determinado produto.

exemplo
{ "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" ] } }

Você pode usar o método withJSON para armazenar essas informações na tabela ProductCatalog, em um atributo Map chamado VendorInfo. O exemplo de código Java a seguir demonstra como fazer isso.

// 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);

Obter um item

Para recuperar um único item, use o método getItem de um objeto Table. Siga estas etapas:

  1. Crie uma instância da classe DynamoDB.

  2. Crie uma instância da classe Table para representar a tabela com a qual você deseja trabalhar.

  3. Chame o método getItem de instância de Table. Você deve especificar a chave primária do item que deseja recuperar.

O exemplo de código Java a seguir demonstra as etapas anteriores. O código obtém o item que tem a chave de partição especificada.

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

Especificar parâmetros opcionais

Além dos parâmetros obrigatórios, você também pode especificar parâmetros opcionais do método getItem. Por exemplo, o seguinte exemplo de código Java usa um método opcional para recuperar somente uma lista específica de atributos e para especificar leituras fortemente consistentes. (Para saber mais sobre a consistência de leitura, consulte Consistência de leituras.)

Você pode usar uma ProjectionExpression para recuperar somente atributos ou elementos específicos, em vez de todo o item. A ProjectionExpression pode especificar atributos aninhados ou de alto nível, usando caminhos de documentos. Para ter mais informações, consulte Expressões de projeção.

Os parâmetros do método getItem não permitem que você especifique consistência de leitura. No entanto, você pode criar uma GetItemSpec que dá acesso total a todas as entradas para a operação GetItem de baixo nível. O exemplo de código a seguir cria uma GetItemSpec e usa essa especificação como entrada para o método getItem.

exemplo
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());

Para imprimir um Item em um formato legível, use o método toJSONPretty. A saída do exemplo anterior é semelhante à seguinte.

{ "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 e documentos JSON

Na seção PutItem e documentos JSON, você armazenou um documento JSON em um atributo Map chamado VendorInfo. Você pode usar o método getItem para recuperar o documento inteiro no formato JSON. Ou pode usar a notação do caminho do documento para recuperar apenas alguns dos elementos no documento. O exemplo de código Java a seguir demonstra essas técnicas.

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());

A saída do exemplo anterior é semelhante à seguinte.

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"]}}}
nota

Você pode usar o método toJSON para converter qualquer item (ou seus atributos) em uma string formatada para JSON. O exemplo de código a seguir recupera vários atributos aninhados e de alto nível e imprime os resultados como JSON.

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

A saída é semelhante à seguinte.

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

Gravação em lote: colocar e excluir vários itens

Gravação em lote se refere a inserir e excluir vários itens em um lote. O método batchWriteItem permite que você insira e exclua vários itens de uma ou mais tabelas em uma única chamada. Veja a seguir as etapas para inserir ou excluir vários itens usando a API de documento do AWS SDK for Java.

  1. Crie uma instância da classe DynamoDB.

  2. Crie uma instância da classe TableWriteItems que descreve todas as operações Put e Delete de uma tabela. Se você quiser gravar em várias tabelas com uma única operação de gravação em lote, crie uma instância de TableWriteItems por tabela.

  3. Chame o método batchWriteItem fornecendo os objetos TableWriteItems que você criou na etapa anterior.

  4. Processe a resposta. Você deve verificar se há itens de solicitação não processados retornados na resposta. Isso poderá acontecer se você atingir a cota de throughput provisionado ou por algum outro erro temporário. Além disso, o DynamoDB limita o tamanho da solicitação e o número de operações que você pode especificar em uma solicitação. Se você exceder esses limites, o DynamoDB rejeitará a solicitação. Para ter mais informações, consulte Service quotas, conta e cotas de tabela no Amazon DynamoDB.

O exemplo de código Java a seguir demonstra as etapas anteriores. O exemplo executa uma operação batchWriteItem em duas tabelas: Forum e Thread. Os objetos TableWriteItems correspondentes definem as seguintes ações:

  • Inserir um item na tabela Forum.

  • Inserir e excluir um item na tabela Thread.

O código chama batchWriteItem para executar a operação.

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

Para obter um exemplo funcional, consulte Exemplo: operação de gravação em lote usando a API de documento do AWS SDK for Java.

Obtenção em lote: obter vários itens

O método batchGetItem permite que você recupere vários itens de uma ou mais tabelas. Para recuperar um único item, você pode usar o método getItem.

Siga estas etapas:

  1. Crie uma instância da classe DynamoDB.

  2. Crie uma instância da classe TableKeysAndAttributes que descreve uma lista de valores de chave primária para recuperar de uma tabela. Se você desejar ler em várias tabelas em uma única operação de aquisição em lote, será necessário criar uma instância de TableKeysAndAttributes por tabela.

  3. Chame o método batchGetItem fornecendo os objetos TableKeysAndAttributes que você criou na etapa anterior.

O exemplo de código Java a seguir demonstra as etapas anteriores. O exemplo recupera dois itens da tabela Forum e três itens da tabela 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); } }

Especificar parâmetros opcionais

Além dos parâmetros obrigatórios, você também pode especificar parâmetros opcionais ao usar batchGetItem. Por exemplo, você pode fornecer uma ProjectionExpression com cada TableKeysAndAttributes que você definir. Isso permite que você especifique os atributos que deseja recuperar da tabela.

O exemplo de código a seguir recupera dois itens da tabela Forum. O parâmetro withProjectionExpression especifica que apenas o atributo Threads deve ser recuperado.

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

Atualizar um item

O método updateItem de um objeto Table pode atualizar valores de atributo existentes, adicionar novos atributos ou excluir atributos de um item existente.

O método updateItem se comporta da seguinte forma:

  • Se não existir um item (não houver nenhum item na tabela com a chave primária especificada), updateItem adicionará um novo item à tabela

  • Se existir um item, updateItem executará a atualização conforme especificado pelo parâmetro UpdateExpression.

nota

Também é possível "atualizar" um item usando putItem. Por exemplo, se você chamar putItem para adicionar um item à tabela, mas já existir um item com a chave primária especificada, putItem substituirá o item inteiro. Se houver atributos no item existente que não são especificados na entrada, putItem removerá esses atributos do item.

Em geral, recomendamos que você use updateItem sempre que desejar modificar quaisquer atributos de item. O método updateItem só modifica os atributos de item que você especifica na entrada, e os outros atributos no item permanecem inalterados.

Siga estas etapas:

  1. Crie uma instância da classe Table para representar a tabela com a qual você deseja trabalhar.

  2. Chame o método updateTable de instância de Table. Você deve especificar a chave primária do item que deseja recuperar, juntamente com uma UpdateExpression que descreve os atributos a serem modificados e como modificá-los.

O exemplo de código Java a seguir demonstra as tarefas anteriores. O código atualiza um item na tabela ProductCatalog. Ele adiciona um novo autor ao conjunto de Authors e exclui o atributo ISBN existente. Ele também reduz o preço por um.

Um mapa ExpressionAttributeValues é usado na UpdateExpression. Os espaços reservados :val1 e :val2 serão substituídos em tempo de execução pelos valores reais de Authors e Price.

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

Especificar parâmetros opcionais

Além dos parâmetros obrigatórios, você também pode especificar parâmetros opcionais para o método updateItem, incluindo uma condição que deve ser atendida para que a atualização ocorra. Se a condição que você especificar não for atendida, o AWS SDK for Java lançará uma ConditionalCheckFailedException. Por exemplo, o seguinte exemplo de código Java atualiza condicionalmente o preço de item de um livro para 25. Ele especifica uma ConditionExpression que declara que o preço deve ser atualizado somente se o preço existente for 20.

exemplo
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);

Contador atômico

Você pode usar updateItem para implementar um contador atômico, onde pode aumentar ou reduzir o valor de um atributo existente sem interferir em outras solicitações de gravação. Para aumentar um contador atômico, use uma UpdateExpression com uma ação set para adicionar um valor numérico a um atributo existente do tipo Number.

O exemplo de código a seguir demonstra isso incrementando o atributo Quantity em um. Ele também demonstra o uso do parâmetro ExpressionAttributeNames em uma 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);

Excluir um item

O método deleteItem exclui um item de uma tabela. É necessário fornecer a chave primária do item que você deseja excluir.

Siga estas etapas:

  1. Crie uma instância do cliente DynamoDB.

  2. Chame o método deleteItem, fornecendo a chave do item que você deseja excluir.

O exemplo de código Java a seguir demonstra essas tarefas.

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

Especificar parâmetros opcionais

Você pode especificar parâmetros opcionais para deleteItem. Por exemplo, o seguinte exemplo de código Java especifica uma ConditionExpression que declara que um item de livro em ProductCatalog só pode ser excluído se o livro não estiver mais em publicação (o atributo InPublication é falso).

exemplo
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);