Uso de elementos: Java - Amazon DynamoDB

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Uso de elementos: Java

Puede usar la API de documentos del AWS SDK for Java para realizar operaciones típicas de creación, lectura, actualización y eliminación (CRUD, por sus siglas en inglés) en los elementos de una tabla de Amazon DynamoDB.

nota

Además, SDK para Java proporciona un modelo de persistencia de objetos, que le permite mapear las clases del lado del cliente a las tablas de DynamoDB. Este enfoque puede reducir la cantidad de código que hay que escribir. Para obtener más información, consulte Java 1.x: DynamoDBMapper.

Esta sección contiene ejemplos de Java que permiten realizar diversas acciones con elementos de la API de documentos de Java y varios ejemplos de trabajo completos.

Colocación de un elemento

El método putItem almacena un elemento en una tabla. Si el elemento existe, sustituye el elemento completo. En lugar de ello, si prefiere actualizar solamente algunos atributos concretos, puede usar el método updateItem. Para obtener más información, consulte Actualización de un elemento.

Siga estos pasos:

  1. Cree una instancia de la clase DynamoDB.

  2. Cree una instancia de la clase Table para representar la tabla que desea usar.

  3. Cree una instancia de la clase Item para representar el nuevo elemento. Debe especificar la clave principal del nuevo elemento y sus atributos.

  4. Llame al método putItem del objeto Table utilizando el Item que creó en el paso anterior.

En el siguiente ejemplo de código Java se muestran las tareas anteriores. El código escribe un nuevo elemento en la tabla ProductCatalog.

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

En el ejemplo anterior, el elemento tiene atributos que son escalares (String, Number, Boolean, Null), conjuntos (String Set) y tipos de documentos (List, Map).

Especificación de parámetros opcionales

Junto con los parámetros requeridos, puede especificar también otros opcionales en el método putItem. Por ejemplo, en el ejemplo de código Java siguiente se utiliza un parámetro opcional que permite especificar una condición para cargar el elemento. Si la condición especificada no se cumple, AWS SDK for Java genera una excepción ConditionalCheckFailedException. En el ejemplo de código se especifican los parámetros opcionales siguientes en el método putItem:

  • Una expresión ConditionExpression que define las condiciones de la solicitud. El código define la condición siguiente: si el elemento existente tiene la misma clave principal, solo se sustituirá si tiene también un atributo ISBN igual a un valor específico.

  • Un mapa de ExpressionAttributeValues que se usa en la condición. En este caso, solo se requiere una sustitución: el marcador de posición :val de la expresión de condición se sustituye en el tiempo de ejecución por el valor de ISBN real que se va a comprobar.

En el siguiente ejemplo se agrega un nuevo elemento de libro utilizando estos parámetros opcionales.

ejemplo
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 y documentos JSON

Puede almacenar un documento JSON como atributo en una tabla de DynamoDB. Para ello, se utiliza el método withJSON de Item. Este método analiza el documento JSON y mapea cada componente a un tipo de datos nativo de DynamoDB.

Suponga que desea almacenar el siguiente documento JSON, que contiene los proveedores que pueden servir pedidos de un producto determinado.

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

Puede utilizar el método withJSON para almacenar esta información en la tabla ProductCatalog en un atributo de tipo Map denominado VendorInfo. En el siguiente ejemplo de código Java se muestra cómo hacerlo.

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

Obtención de un elemento

Para recuperar un solo elemento, utilice el método getItem de un objeto Table. Siga estos pasos:

  1. Cree una instancia de la clase DynamoDB.

  2. Cree una instancia de la clase Table para representar la tabla que desea usar.

  3. Llame al método getItem de la instancia de Table. Es preciso especificar la clave principal del elemento que se desea recuperar.

En el siguiente ejemplo de código Java se muestran los pasos anteriores. El código obtiene el elemento que tiene la clave de partición especificada.

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

Especificación de parámetros opcionales

Junto con los parámetros requeridos, puede especificar también otros opcionales del método getItem. Por ejemplo, en el siguiente ejemplo de código Java se utiliza un método opcional para recuperar solo una lista concreta de atributos y especificar lecturas de consistencia alta. Para obtener más información sobre la consistencia de lectura, consulte Coherencia de lectura.

Puede usar una expresión ProjectionExpression para recuperar solamente algunos atributos o componentes concretos, en lugar de un elemento completo. Una expresión ProjectionExpression permite especificar atributos de nivel superior o anidados mediante rutas de documentos. Para obtener más información, consulte Expresiones de proyección.

Los parámetros del método getItem no permiten especificar la consistencia de .lectura Sin embargo, puede crear una especificación GetItemSpec, que proporciona acceso pleno a toda la información de entrada de la operación de bajo nivel GetItem. En el ejemplo de código siguiente se crea una especificación GetItemSpec y se utiliza como información de entrada para el método getItem.

ejemplo
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 un Item en formato fácil de leer, utilice el método toJSONPretty. El resultado del ejemplo anterior tiene este aspecto.

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

En la sección PutItem y documentos JSON, almacena un documento JSON en un atributo Map denominado VendorInfo. Puede utilizar el método getItem para recuperar todo el documento en formato JSON. O puede usar la notación de ruta de documento para recuperar solo algunos de los componentes de ese documento. En el siguiente ejemplo de código Java se muestran estas 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());

El resultado del ejemplo anterior tiene este aspecto.

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

Puede usar el método toJSON para convertir cualquier elemento (o sus atributos) en una cadena con formato JSON. En el siguiente ejemplo de código se recuperan varios atributos de nivel superior y anidados y se imprimen los 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());

El resultado es similar al siguiente.

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

Escritura por lotes: colocación y eliminación de varios elementos

La escritura por lotes se refiere a colocar y eliminar varios elementos en un lote. El método batchWriteItem permite colocar y eliminar varios elementos de una o varias tablas con una sola llamada. A continuación se indican los pasos para colocar o eliminar varios elementos mediante la API de documentos del AWS SDK for Java.

  1. Cree una instancia de la clase DynamoDB.

  2. Cree una instancia de la clase TableWriteItems que describe todas las operaciones de colocación y eliminación de una tabla. Si desea escribir en varias tablas en una misma operación de escritura por lotes, debe crear una instancia de TableWriteItems por cada tabla.

  3. Llame al método batchWriteItem proporcionando los objetos TableWriteItems que creó en el paso anterior.

  4. Procese la respuesta. Debe comprobar si en la respuesta se ha devuelto algún elemento de solicitud sin procesar. Esto puede ocurrir si se alcanza la cuota de rendimiento aprovisionado o se produce algún otro error transitorio. Además, DynamoDB limita el tamaño de la solicitud y el número de operaciones que se pueden especificar en ella. Si supera estos límites, DynamoDB rechaza la solicitud. Para obtener más información, consulte Cuotas de tabla, servicio y cuenta en Amazon DynamoDB.

En el siguiente ejemplo de código Java se muestran los pasos anteriores. El ejemplo lleva a cabo una operación batchWriteItem en dos tablas: Forum y Thread. Los objetos TableWriteItems correspondientes definen las siguientes acciones:

  • Colocar un elemento en la tabla Forum.

  • Colocar y eliminar un elemento en la tabla Thread.

A continuación, el código llama a batchWriteItem para llevar a cabo la operación.

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 ver un ejemplo práctico, consulte Ejemplo: operación de escritura por lotes mediante la API de documentos de AWS SDK for Java.

Obtención por lotes: obtención de varios elementos

El método batchGetItem permite recuperar varios elementos de una o varias tablas. Para recuperar un solo elemento, puede usar el método getItem.

Siga estos pasos:

  1. Cree una instancia de la clase DynamoDB.

  2. Cree una instancia de la clase TableKeysAndAttributes que describe una lista de valores de clave principal que se van a recuperar de una tabla. Si desea leer de varias tablas en una misma operación de obtención por lotes, debe crear una instancia de TableKeysAndAttributes por cada tabla.

  3. Llame al método batchGetItem proporcionando los objetos TableKeysAndAttributes que creó en el paso anterior.

En el siguiente ejemplo de código Java se muestran los pasos anteriores. El ejemplo recupera dos elementos de la tabla Forum y tres de la tabla 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); } }

Especificación de parámetros opcionales

Junto con los parámetros requeridos, puede especificar también otros opcionales cuando use batchGetItem. Por ejemplo, puede proporcionar una expresión ProjectionExpression con cada TableKeysAndAttributes que defina. Esto le permite especificar los atributos que desea recuperar de la tabla.

En el siguiente ejemplo de código se recuperan dos elementos de la tabla Forum. El parámetro withProjectionExpression especifica que solamente hay que recuperar el atributo Threads.

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

Actualización de un elemento

El método updateItem de un objeto Table permite actualizar los valores de atributos presentes, agregar atributos nuevos o eliminarlos de un elemento existente.

El método updateItem se comporta de la siguiente manera:

  • Si un elemento no existe (no hay ningún elemento en la tabla con la clave principal especificada), updateItem agrega un elemento nuevo a la tabla.

  • Si un elemento ya existe, updateItem lleva a cabo la actualización según lo especificado en el parámetro UpdateExpression.

nota

También es posible actualizar un elemento mediante putItem. Por ejemplo, si llama a putItem para agregar un elemento a la tabla pero ya existe uno con la clave principal especificada, putItem sustituye el elemento completo. Si hay atributos en el elemento existente que no se especifican en la información de entrada, putItem los elimina del elemento.

En general, recomendamos usar updateItem siempre que desee modificar atributos de elementos. El método updateItem solo modifica los atributos del elemento que especifique en la información de entrada, pero deja los demás atributos del elemento tal cual estaban.

Siga estos pasos:

  1. Cree una instancia de la clase Table para representar la tabla que desea usar.

  2. Llame al método updateTable de la instancia de Table. Debe especificar la clave principal del elemento que desea recuperar, junto con una expresión UpdateExpression que describa los atributos que hay que cambiar y cómo modificarlos.

En el siguiente ejemplo de código Java se muestran las tareas anteriores. El código actualiza un elemento de libro en la tabla ProductCatalog. Se agrega un nuevo autor al conjunto Authors y se elimina el atributo ISBN existente. También se reduce el precio en una unidad.

Se utiliza un mapa ExpressionAttributeValues en UpdateExpression. Los marcadores de posición :val1 y :val2 se sustituyen en tiempo de ejecución por los valores reales de Authors y 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);

Especificación de parámetros opcionales

Junto con los parámetros requeridos, puede especificar también parámetros opcionales para el método updateItem, incluida una condición que debe cumplirse para que se lleve a cabo la actualización. Si la condición especificada no se cumple, AWS SDK for Java genera una excepción ConditionalCheckFailedException. Por ejemplo, el siguiente ejemplo de código Java actualiza de forma condicional el precio de un elemento de libro a 25. Especifica una expresión ConditionExpression en la que se indica que el precio solo debe actualizarse si el precio actual es 20.

ejemplo
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

Puede usar updateItem para implementar un contador atómico y aumentar o reducir el valor de un atributo existente sin interferir con las demás solicitudes de escritura. Para incrementar un contador atómico, use una expresión UpdateExpression con la acción set para sumar un valor numérico a una atributo existente de tipo Number.

En el siguiente ejemplo se pone en práctica lo anterior y se incrementa el atributo Quantity en una unidad. También se demuestra cómo usar el parámetro ExpressionAttributeNames en una expresión 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);

Eliminación de un elemento

El método deleteItem elimina un elemento de una tabla. Es preciso proporcionar la clave principal del elemento que se desea eliminar.

Siga estos pasos:

  1. Cree una instancia del cliente de DynamoDB.

  2. Llame al método deleteItem proporcionando la clave del elemento que desea eliminar.

En el siguiente ejemplo de Java se muestran estas tareas.

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

Especificación de parámetros opcionales

Puede especificar parámetros opcionales para deleteItem. Por ejemplo, el siguiente ejemplo de código Java incluye una expresión ConditionExpression que indica que un elemento de libro de ProductCatalog solo se puede eliminar si el libro está descatalogado (el atributo InPublication es false).

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