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.
Realizar operaciones de transacciones
El API cliente mejorado de DynamoDB proporciona los métodos y transactGetItems()
los métodos. transactWriteItems()
Los métodos de transacción de Java proporcionan atomicidad, coherencia, aislamiento y durabilidad (ACID) en las tablas de DynamoDB, lo que le ayuda a mantener la exactitud de los datos en sus aplicaciones. SDK
transactGetItems()
Ejemplo de
El método transactGetItems()
admite hasta 100 solicitudes individuales de artículos. Todos los artículos se leen en una sola transacción atómica. La Guía para desarrolladores de Amazon DynamoDB contiene información sobre las condiciones que hacen que un método transactGetItems()
falle, y también sobre el nivel de aislamiento utilizado cuando se llama a transactGetItem()
.
Tras la línea de comentarios 1 del siguiente ejemplo, el código llama al método transactGetItems()
con un parámetro builder
. El generador addGetItem()
se invoca tres veces con un objeto de datos que contiene los valores clave que SDK se utilizarán para generar la solicitud final.
La solicitud devuelve una lista de objetos Document
después de la línea de comentarios 2. La lista de documentos que se devuelve contiene instancias de documentosDocument.getItem(MappedTableResource<T> mappedTableResource)
convierte un objeto sin tipo en un objeto Document
Java con tipo si se devolvieron los datos del elemento; de lo contrario, el método devuelve un valor nulo.
public static void transactGetItemsExample(DynamoDbEnhancedClient enhancedClient, DynamoDbTable<ProductCatalog> catalogTable, DynamoDbTable<MovieActor> movieActorTable) { // 1. Request three items from two tables using a builder. final List<Document> documents = enhancedClient.transactGetItems(b -> b .addGetItem(catalogTable, Key.builder().partitionValue(2).sortValue("Title 55").build()) .addGetItem(movieActorTable, Key.builder().partitionValue("Sophie's Choice").sortValue("Meryl Streep").build()) .addGetItem(movieActorTable, Key.builder().partitionValue("Blue Jasmine").sortValue("Cate Blanchett").build()) .build()); // 2. A list of Document objects is returned in the same order as requested. ProductCatalog title55 = documents.get(0).getItem(catalogTable); if (title55 != null) { logger.info(title55.toString()); } MovieActor sophiesChoice = documents.get(1).getItem(movieActorTable); if (sophiesChoice != null) { logger.info(sophiesChoice.toString()); } // 3. The getItem() method returns null if the Document object contains no item from DynamoDB. MovieActor blueJasmine = documents.get(2).getItem(movieActorTable); if (blueJasmine != null) { logger.info(blueJasmine.toString()); } }
Las tablas de DynamoDB contienen los siguientes elementos antes de que se ejecute el ejemplo de código.
ProductCatalog{id=2, title='Title 55', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
Se registra la siguiente salida. Si se solicita un elemento pero no se encuentra, no se devuelve, como ocurre con la solicitud de la película nombrada Blue Jasmine
.
ProductCatalog{id=2, title='Title 55', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
Ejemplos de transactWriteItems()
El transactWriteItems()
acepta hasta 100 acciones para colocar, actualizar o eliminar en una única transacción atómica a través de varias tablas. La Guía para desarrolladores de Amazon DynamoDB contiene detalles sobre las restricciones y las condiciones de fallo del funcionamiento del servicio DynamoDB subyacente.
Ejemplo básico
En el ejemplo siguiente, se solicitan cuatro operaciones para dos tablas. Las clases de modelos correspondientes ProductCatalog y MovieActor se mostraron anteriormente.
Cada una de las tres operaciones posibles (poner, actualizar y eliminar) utiliza un parámetro de solicitud específico para especificar los detalles.
El código bajo la línea de comentarios 1 muestra la variación simple del método addPutItem()
. El método acepta un objeto MappedTableResource
y la instancia del objeto de datos para colocarlo. La declaración que sigue a la línea de comentarios 2 muestra la variación que acepta una instancia TransactPutItemEnhancedRequest
. Esta variante permite añadir más opciones a la solicitud, como una expresión de condición. En un ejemplo posterior, se muestra una expresión de condición para una operación individual.
Se solicita una operación de actualización después de la línea de comentarios 3. TransactUpdateItemEnhancedRequest
tiene un ignoreNulls()
método que permite configurar lo que SDK hace con null
los valores del objeto modelo. Si el ignoreNulls()
método devuelve el valor true, SDK no elimina los valores de los atributos de la tabla para los atributos del objeto de datos que sí lo sonnull
. Si el ignoreNulls()
método devuelve false, SDK solicita al servicio DynamoDB que elimine los atributos del elemento de la tabla. El valor predeterminado de ignoreNulls
es false.
La instrucción tras la línea de comentario 4 muestra la variación de una petición de borrado que toma un objeto de datos. El cliente mejorado extrae los valores clave antes de enviar la solicitud final.
public static void transactWriteItems(DynamoDbEnhancedClient enhancedClient, DynamoDbTable<ProductCatalog> catalogTable, DynamoDbTable<MovieActor> movieActorTable) { enhancedClient.transactWriteItems(b -> b // 1. Simplest variation of put item request. .addPutItem(catalogTable, getProductCatId2()) // 2. Put item request variation that accommodates condition expressions. .addPutItem(movieActorTable, TransactPutItemEnhancedRequest.builder(MovieActor.class) .item(getMovieActorStreep()) .conditionExpression(Expression.builder().expression("attribute_not_exists (movie)").build()) .build()) // 3. Update request that does not remove attribute values on the table if the data object's value is null. .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class) .item(getProductCatId4ForUpdate()) .ignoreNulls(Boolean.TRUE) .build()) // 4. Variation of delete request that accepts a data object. The key values are extracted for the request. .addDeleteItem(movieActorTable, getMovieActorBlanchett()) ); }
Los siguientes métodos auxiliares proporcionan los objetos de datos para los parámetros add*Item
.
public static ProductCatalog getProductCatId2() { return ProductCatalog.builder() .id(2) .isbn("1-565-85698") .authors(new HashSet<>(Arrays.asList("a", "b"))) .price(BigDecimal.valueOf(30.22)) .title("Title 55") .build(); } public static ProductCatalog getProductCatId4ForUpdate() { return ProductCatalog.builder() .id(4) .price(BigDecimal.valueOf(40.00)) .title("Title 1") .build(); } public static MovieActor getMovieActorBlanchett() { MovieActor movieActor = new MovieActor(); movieActor.setActorName("Cate Blanchett"); movieActor.setMovieName("Tar"); movieActor.setActingYear(2022); movieActor.setActingAward("Best Actress"); movieActor.setActingSchoolName("National Institute of Dramatic Art"); return movieActor; } public static MovieActor getMovieActorStreep() { MovieActor movieActor = new MovieActor(); movieActor.setActorName("Meryl Streep"); movieActor.setMovieName("Sophie's Choice"); movieActor.setActingYear(1982); movieActor.setActingAward("Best Actress"); movieActor.setActingSchoolName("Yale School of Drama"); return movieActor; }
Las tablas de DynamoDB contienen los siguientes elementos antes de que se ejecute el ejemplo de código.
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
Los siguientes elementos aparecen en las tablas después de que el código termine de ejecutarse.
3 | ProductCatalog{id=2, title='Title 55', isbn='1-565-85698', authors=[a, b], price=30.22}
4 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=40.0}
5 | MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
Se ha eliminado el elemento de la línea 2 y las líneas 3 y 5 muestran los elementos que se colocaron. La línea 4 muestra la actualización de la línea 1. El valor price
es el único que ha cambiado en el artículo. Si ignoreNulls()
hubiera devuelto false, la línea 4 tendría el siguiente aspecto.
ProductCatalog{id=4, title='Title 1', isbn='null', authors=null, price=40.0}
Ejemplo de comprobación de estado
En el siguiente ejemplo, se muestra el uso de una comprobación de estado. Una comprobación de estado se utiliza para comprobar la existencia de un elemento o para comprobar el estado de atributos concretos de un elemento en la base de datos. El artículo registrado en la verificación de estado no se puede utilizar en otra operación de la transacción.
nota
No se pueden dirigir varias operaciones de la misma transacción al mismo elemento. Por ejemplo, no puede llevar a cabo una comprobación de condiciones y además intentar actualizar el mismo artículo en la misma transacción.
El ejemplo muestra una operación de cada tipo en una solicitud transaccional de escritura de artículos. Después de la línea de comentario 2, el método addConditionCheck()
suministra la condición que falla la transacción si el parámetro conditionExpression
se evalúa como false
. La expresión de condición que devuelve el método mostrado en el bloque Métodos auxiliares comprueba si el año de concesión de la película Sophie's
Choice
no es igual a 1982
. Si es así, la expresión se evalúa como false
y la transacción no se realiza correctamente.
Esta guía analiza en profundidad las expresiones en otro tema.
public static void conditionCheckFailExample(DynamoDbEnhancedClient enhancedClient, DynamoDbTable<ProductCatalog> catalogTable, DynamoDbTable<MovieActor> movieActorTable) { try { enhancedClient.transactWriteItems(b -> b // 1. Perform one of each type of operation with the next three methods. .addPutItem(catalogTable, TransactPutItemEnhancedRequest.builder(ProductCatalog.class) .item(getProductCatId2()).build()) .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class) .item(getProductCatId4ForUpdate()) .ignoreNulls(Boolean.TRUE).build()) .addDeleteItem(movieActorTable, TransactDeleteItemEnhancedRequest.builder() .key(b1 -> b1 .partitionValue(getMovieActorBlanchett().getMovieName()) .sortValue(getMovieActorBlanchett().getActorName())).build()) // 2. Add a condition check on a table item that is not involved in another operation in this request. .addConditionCheck(movieActorTable, ConditionCheck.builder() .conditionExpression(buildConditionCheckExpression()) .key(k -> k .partitionValue("Sophie's Choice") .sortValue("Meryl Streep")) // 3. Specify the request to return existing values from the item if the condition evaluates to true. .returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD) .build()) .build()); // 4. Catch the exception if the transaction fails and log the information. } catch (TransactionCanceledException ex) { ex.cancellationReasons().stream().forEach(cancellationReason -> { logger.info(cancellationReason.toString()); }); } }
En el ejemplo de código anterior se utilizan los siguientes métodos auxiliares.
private static Expression buildConditionCheckExpression() { Map<String, AttributeValue> expressionValue = Map.of( ":year", numberValue(1982)); return Expression.builder() .expression("actingyear <> :year") .expressionValues(expressionValue) .build(); } public static ProductCatalog getProductCatId2() { return ProductCatalog.builder() .id(2) .isbn("1-565-85698") .authors(new HashSet<>(Arrays.asList("a", "b"))) .price(BigDecimal.valueOf(30.22)) .title("Title 55") .build(); } public static ProductCatalog getProductCatId4ForUpdate() { return ProductCatalog.builder() .id(4) .price(BigDecimal.valueOf(40.00)) .title("Title 1") .build(); } public static MovieActor getMovieActorBlanchett() { MovieActor movieActor = new MovieActor(); movieActor.setActorName("Cate Blanchett"); movieActor.setMovieName("Blue Jasmine"); movieActor.setActingYear(2013); movieActor.setActingAward("Best Actress"); movieActor.setActingSchoolName("National Institute of Dramatic Art"); return movieActor; }
Las tablas de DynamoDB contienen los siguientes elementos antes de que se ejecute el ejemplo de código.
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
3 | MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
Los siguientes elementos aparecen en las tablas después de que el código termine de ejecutarse.
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
Los elementos permanecen sin cambios en las tablas porque se produjo un error en la transacción. El valor actingYear
de la película Sophie's Choice
es 1982
, como muestra la línea 2 de los elementos de la tabla antes de llamar al método transactWriteItem()
.
Para capturar la información de cancelación de la transacción, incluya la llamada al método transactWriteItems()
en un bloque try
y catch
el TransactionCanceledException
CancellationReason
. Dado que el código que sigue a la línea de comentario 3 del ejemplo especifica que deben devolverse los valores del elemento que provocó el fallo de la transacción, el registro muestra los valores brutos de la base de datos para el elemento de la película Sophie's
Choice
.
CancellationReason(Code=None) CancellationReason(Code=None) CancellationReason(Code=None) CancellationReason(Item={actor=AttributeValue(S=Meryl Streep), movie=AttributeValue(S=Sophie's Choice), actingaward=AttributeValue(S=Best Actress), actingyear=AttributeValue(N=1982), actingschoolname=AttributeValue(S=Yale School of Drama)}, ¬ Code=ConditionalCheckFailed, Message=The conditional request failed.)
Ejemplo de condición de operación única
El siguiente ejemplo muestra el uso de una condición en una sola operación de una solicitud de transacción. La operación de eliminación después de la línea de comentarios 1 contiene una condición que compara el valor del elemento objetivo de la operación con la base de datos. En este ejemplo, la expresión de condición creada con el método auxiliar después de la línea de comentario 2 especifica que el elemento debe eliminarse de la base de datos si el año de actuación de la película no es igual a 2013.
Las expresiones se describen más adelante en esta guía.
public static void singleOperationConditionFailExample(DynamoDbEnhancedClient enhancedClient, DynamoDbTable<ProductCatalog> catalogTable, DynamoDbTable<MovieActor> movieActorTable) { try { enhancedClient.transactWriteItems(b -> b .addPutItem(catalogTable, TransactPutItemEnhancedRequest.builder(ProductCatalog.class) .item(getProductCatId2()) .build()) .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class) .item(getProductCatId4ForUpdate()) .ignoreNulls(Boolean.TRUE).build()) // 1. Delete operation that contains a condition expression .addDeleteItem(movieActorTable, TransactDeleteItemEnhancedRequest.builder() .key((Key.Builder k) -> { MovieActor blanchett = getMovieActorBlanchett(); k.partitionValue(blanchett.getMovieName()) .sortValue(blanchett.getActorName()); }) .conditionExpression(buildDeleteItemExpression()) .returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD) .build()) .build()); } catch (TransactionCanceledException ex) { ex.cancellationReasons().forEach(cancellationReason -> logger.info(cancellationReason.toString())); } } // 2. Provide condition expression to check if 'actingyear' is not equal to 2013. private static Expression buildDeleteItemExpression() { Map<String, AttributeValue> expressionValue = Map.of( ":year", numberValue(2013)); return Expression.builder() .expression("actingyear <> :year") .expressionValues(expressionValue) .build(); }
En el ejemplo de código anterior se utilizan los siguientes métodos auxiliares.
public static ProductCatalog getProductCatId2() { return ProductCatalog.builder() .id(2) .isbn("1-565-85698") .authors(new HashSet<>(Arrays.asList("a", "b"))) .price(BigDecimal.valueOf(30.22)) .title("Title 55") .build(); } public static ProductCatalog getProductCatId4ForUpdate() { return ProductCatalog.builder() .id(4) .price(BigDecimal.valueOf(40.00)) .title("Title 1") .build(); } public static MovieActor getMovieActorBlanchett() { MovieActor movieActor = new MovieActor(); movieActor.setActorName("Cate Blanchett"); movieActor.setMovieName("Blue Jasmine"); movieActor.setActingYear(2013); movieActor.setActingAward("Best Actress"); movieActor.setActingSchoolName("National Institute of Dramatic Art"); return movieActor; }
Las tablas de DynamoDB contienen los siguientes elementos antes de que se ejecute el ejemplo de código.
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
Los siguientes elementos aparecen en las tablas después de que el código termine de ejecutarse.
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2023-03-15 11:29:07 [main] INFO org.example.tests.TransactDemoTest:168 - MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
Los elementos permanecen sin cambios en las tablas porque se produjo un error en la transacción. El valor actingYear
para la película Blue Jasmine
es 2013
como se muestra en la línea 2 de la lista de elementos antes de que se ejecute el ejemplo de código.
Las líneas siguientes se registran en la consola.
CancellationReason(Code=None) CancellationReason(Code=None) CancellationReason(Item={actor=AttributeValue(S=Cate Blanchett), movie=AttributeValue(S=Blue Jasmine), actingaward=AttributeValue(S=Best Actress), actingyear=AttributeValue(N=2013), actingschoolname=AttributeValue(S=National Institute of Dramatic Art)}, Code=ConditionalCheckFailed, Message=The conditional request failed)