Cambios en las API de asignación de DynamoDB entre las versiones 1 y 2 del SDK para Java - AWS SDK for Java 2.x

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.

Cambios en las API de asignación de DynamoDB entre las versiones 1 y 2 del SDK para Java

Crear un cliente

Caso de uso V1 V2

Instanciación normal

AmazonDynamoDB standardClient = AmazonDynamoDBClientBuilder.standard() .withCredentials(credentialsProvider) .withRegion(Regions.US_EAST_1) .build(); DynamoDBMapper mapper = new DynamoDBMapper(standardClient);
DynamoDbClient standardClient = DynamoDbClient.builder() .credentialsProvider(ProfileCredentialsProvider.create()) .region(Region.US_EAST_1) .build(); DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(standardClient) .build();

Instanciación mínima

AmazonDynamoDB standardClient = AmazonDynamoDBClientBuilder.standard(); DynamoDBMapper mapper = new DynamoDBMapper(standardClient);
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create();

Con transformador de atributos*

DynamoDBMapper mapper = new DynamoDBMapper(standardClient, attributeTransformerInstance);
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(standardClient) .extensions(extensionAInstance, extensionBInstance) .build();

*Las extensiones de V2 corresponden aproximadamente a los transformadores de atributos de V1. La sección Uso de extensiones para personalizar operaciones de DynamoDB Enhanced Client contiene más información sobre extensiones de V2.

Establecimiento de asignación a tabla/índice de DynamoDB

En V1, se especifica un nombre de tabla de DynamoDB mediante una anotación de bean. En V2, un método de fábrica, table(), produce una instancia de DynamoDbTable que representa la tabla remota de DynamoDB. El primer parámetro del método table() es el nombre de tabla de DynamoDB.

Caso de uso V1 V2

Asignar la clase POJO de Java a la tabla de DynamoDB

@DynamoDBTable(tableName ="Customer") public class Customer { ... }
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));

Asignar a un índice secundario de DynamoDB

  1. Defina una clase POJO que represente el índice.

    • Anote la clase con @DynamoDBTable proporcionando el nombre de la tabla que contiene el índice.

    • Anote propiedades con @DynamoDBIndexHashKey y, opcionalmente, @DynamoDBIndexRangeKey.

  2. Cree una expresión de consulta.

  3. Consulte haciendo referencia a la clase POJO que representa el índice. Por ejemplo

    mapper.query(IdEmailIndex.class, queryExpression)

    donde IdEmailIndex es la clase de asignación del índice.

En la sección de la Guía para desarrolladores de DynamoDB que analiza el método de query V1 se muestra un ejemplo completo.

  1. Anote atributos de una clase POJO con @DynamoDbSecondaryPartitionKey (para un GSI) y @DynamoDbSecondarySortKey (para un GSI o LSI). Por ejemplo:

    @DynamoDbSecondarySortKey(indexNames = "IdEmailIndex") public String getEmail() { return this.email; }
  2. Recupere una referencia al índice. Por ejemplo:

    DynamoDbIndex<Customer> customerIndex = customerTable.index("IdEmailIndex");
  3. Consulte el índice.

En la sección Usar índices secundarios de esta guía se proporciona más información.

Operaciones de tabla

En esta sección se describen las API de operación que difieren entre la V1 y la V2 en la mayoría de los casos de uso estándar.

En la V2, todas las operaciones que implican una sola tabla se llaman en la instancia de DynamoDbTable, no en el cliente mejorado. El cliente mejorado contiene métodos que pueden referirse a varias tablas.

En la tabla denominada Operaciones de tabla que aparece a continuación, se hace referencia a una instancia de POJO como item o como tipo específico, por ejemplo customer1. En los ejemplos de la V2, la instancia llamada table es resultado de una llamada anterior a enhancedClient.table() que devuelve una referencia a la instancia DynamoDbTable.

Tenga en cuenta que la mayoría de las operaciones de la V2 se pueden llamar con un patrón de consumo fluido, incluso cuando no se muestran. Por ejemplo:

Customer customer = table.getItem(r → r.key(key)); or Customer customer = table.getItem(r → r.key(k -> k.partitionValue("id").sortValue("email")))

Para las operaciones de la V1, Operaciones de tabla (a continuación) contiene algunos de los formularios más utilizados y no todos los formularios sobrecargados. Por ejemplo, el método load() presenta las siguientes sobrecargas:

mapper.load(Customer.class, hashKey) mapper.load(Customer.class, hashKey, rangeKey) mapper.load(Customer.class, hashKey, config) mapper.load(Customer.class, hashKey, rangeKey, config) mapper.load(item) mapper.load(item, config)

Operaciones de tabla (a continuación) muestra los formularios más utilizados:

mapper.load(item) mapper.load(item, config)
Operaciones de tabla
Caso de uso V1 V2

Escribir un POJO de Java en una tabla de DynamoDB

Operación de DynamoDB: PutItem, UpdateItem

mapper.save(item) mapper.save(item, config) mapper.save(item, saveExpression, config)

En la V1, DynamoDBMapperConfig.SaveBehavior y las anotaciones determinan a qué método de DynamoDB de bajo nivel se llamará. En general, se llama a UpdateItem excepto cuando se usa SaveBehavior.CLOBBER y SaveBehavior.PUT. Las claves generadas automáticamente son un caso de uso especial y, en ocasiones, se utilizan PutItem y UpdateItem.

table.putItem(putItemRequest) table.putItem(item) table.putItemWithResponse(item) //Returns metadata. updateItem(updateItemRequest) table.updateItem(item) table.updateItemWithResponse(item) //Returns metadata.

Leer un elemento de una tabla de DynamoDB a un POJO de Java

Operación de DynamoDB: GetItem

mapper.load(item) mapper.load(item, config)
table.getItem(getItemRequest) table.getItem(item) table.getItem(key) table.getItemWithResponse(key) //Returns POJO with metadata.

Eliminar un elemento de una tabla de DynamoDB

Operación de DynamoDB: DeleteItem

mapper.delete(item, deleteExpression, config)
table.deleteItem(deleteItemRequest) table.deleteItem(item) table.deleteItem(key)

Consultar una tabla o un índice secundario de DynamoDB y devolución de una lista paginada

Operación de DynamoDB: Query

mapper.query(Customer.class, queryExpression) mapper.query(Customer.class, queryExpression, mapperConfig)
table.query(queryRequest) table.query(queryConditional)

Usar el PageIterable.stream() devuelto (carga diferida) para respuestas sincrónicas y PagePublisher.subscribe() para respuestas asincrónicas

Consultar una tabla o un índice secundario de DynamoDB y devolver una lista

Operación de DynamoDB: Query

mapper.queryPage(Customer.class, queryExpression) mapper.queryPage(Customer.class, queryExpression, mapperConfig)
table.query(queryRequest) table.query(queryConditional)

Usar el PageIterable.items() devuelto (carga diferida) para respuestas sincrónicas y PagePublisher.items.subscribe() para respuestas asincrónicas

Analizar una tabla o un índice secundario de DynamoDB y devolver una lista paginada

Operación de DynamoDB: Scan

mapper.scan(Customer.class, scanExpression) mapper.scan(Customer.class, scanExpression, mapperConfig)
table.scan() table.scan(scanRequest)

Usar el PageIterable.stream() devuelto (carga diferida) para respuestas sincrónicas y PagePublisher.subscribe() para respuestas asincrónicas

Analizar una tabla o un índice secundario de DynamoDB y devolver una lista

Operación de DynamoDB: Scan

mapper.scanPage(Customer.class, scanExpression) mapper.scanPage(Customer.class, scanExpression, mapperConfig)
table.scan() table.scan(scanRequest)

Usar el PageIterable.items() devuelto (carga diferida) para respuestas sincrónicas y PagePublisher.items.subscribe() para respuestas asincrónicas

Leer varios elementos de varias tablas de un lote

Operación de DynamoDB: BatchGetItem

mapper.batchLoad(Arrays.asList(customer1, customer2, book1)) mapper.batchLoad(itemsToGet) // itemsToGet: Map<Class<?>, List<KeyPair>>
enhancedClient.batchGetItem(batchGetItemRequest) enhancedClient.batchGetItem(r -> r.readBatches( ReadBatch.builder(Record1.class) .mappedTableResource(mappedTable1) .addGetItem(i -> i.key(k -> k.partitionValue(0))) .build(), ReadBatch.builder(Record2.class) .mappedTableResource(mappedTable2) .addGetItem(i -> i.key(k -> k.partitionValue(0))) .build())) // Iterate over pages with lazy loading or over all items from the same table.

Escribir varios elementos en varias tablas de un lote

Operación de DynamoDB: BatchWriteItem

mapper.batchSave(Arrays.asList(customer1, customer2, book1))
enhancedClient.batchWriteItem(batchWriteItemRequest) enhancedClient.batchWriteItem(r -> r.writeBatches( WriteBatch.builder(Record1.class) .mappedTableResource(mappedTable1) .addPutItem(item1) .build(), WriteBatch.builder(Record2.class) .mappedTableResource(mappedTable2) .addPutItem(item2) .build()))

Eliminar varios elementos de varias tablas de un lote

Operación de DynamoDB: BatchWriteItem

mapper.batchDelete(Arrays.asList(customer1, customer2, book1))
enhancedClient.batchWriteItem(r -> r.writeBatches( WriteBatch.builder(Record1.class) .mappedTableResource(mappedTable1) .addDeleteItem(item1key) .build(), WriteBatch.builder(Record2.class) .mappedTableResource(mappedTable2) .addDeleteItem(item2key) .build()))

Escribir/eliminar varios elementos de un lote

Operación de DynamoDB: BatchWriteItem

mapper.batchWrite(Arrays.asList(customer1, book1), Arrays.asList(customer2))
enhancedClient.batchWriteItem(r -> r.writeBatches( WriteBatch.builder(Record1.class) .mappedTableResource(mappedTable1) .addPutItem(item1) .build(), WriteBatch.builder(Record2.class) .mappedTableResource(mappedTable2) .addDeleteItem(item2key) .build()))

Realizar una escritura transaccional

Operación de DynamoDB: TransactWriteItems

mapper.transactionWrite(transactionWriteRequest)
enhancedClient.transactWriteItems(transasctWriteItemsRequest)

Realizar una lectura transaccional

Operación de DynamoDB: TransactGetItems

mapper.transactionLoad(transactionLoadRequest)
enhancedClient.transactGetItems(transactGetItemsRequest)

Obtener un recuento de elementos coincidentes de una consulta

Operación de DynamoDB: Query con Select.COUNT

mapper.count(Customer.class, queryExpression)
// Get the count from query results. PageIterable<Customer> pageIterable = customerTable.query(QueryEnhancedRequest.builder() .queryConditional(queryConditional) .select(Select.COUNT) .build()); Iterator<Page<Customer>> iterator = pageIterable.iterator(); Page<Customer> page = iterator.next(); int count = page.count(); // For a more concise approach, you can chain the method calls: int count = customerTable.query(QueryEnhancedRequest.builder() .queryConditional(queryConditional) .select(Select.COUNT) .build()) .iterator().next().count();

Obtener un recuento de elementos coincidentes de un análisis

Operación de DynamoDB: Scan con Select.COUNT

mapper.count(Customer.class, scanExpression)
// Get the count from scan results. PageIterable<Customer> pageIterable = customerTable.scan(ScanEnhancedRequest.builder() .filterExpression(filterExpression) .select(Select.COUNT) .build()); Iterator<Page<Customer>> iterator = pageIterable.iterator(); Page<Customer> page = iterator.next(); int count = page.count(); // For a more concise approach, you can chain the method calls: int count = customerTable.scan(ScanEnhancedRequest.builder() .filterExpression(filterExpression) .select(Select.COUNT) .build()) .iterator().next().count();

Crear una tabla en DynamoDB correspondiente a la clase POJO

Operación de DynamoDB: CreateTable

mapper.generateCreateTableRequest(Customer.class)

La instrucción anterior genera una solicitud de creación de tabla de bajo nivel; los usuarios deben llamar a createTable en el cliente de DynamoDB.

table.createTable(createTableRequest) table.createTable(r -> r.provisionedThroughput(defaultThroughput()) .globalSecondaryIndices( EnhancedGlobalSecondaryIndex.builder() .indexName("gsi_1") .projection(p -> p.projectionType(ProjectionType.ALL)) .provisionedThroughput(defaultThroughput()) .build()));

Realizar un análisis paralelo en DynamoDB

Operación de DynamoDB: Scan con parámetrosSegment y TotalSegments

mapper.parallelScan(Customer.class, scanExpression, numTotalSegments)

Los usuarios deben administrar los subprocesos de trabajo y llamar a scan para cada segmento:

table.scan(r -> r.segment(0).totalSegments(5))

Integración de Amazon S3 con DynamoDB para almacenar enlaces de S3 inteligentes

mapper.createS3Link(bucket, key) mapper.getS3ClientCache()

No se admite porque acopla Amazon S3 y DynamoDB.

Asignación de clases y propiedades

Tanto en la V1 como en la V2, las clases se asignan a tablas mediante anotaciones de tipo bean. La V2 también ofrece otras formas de definir esquemas para casos de uso específicos, como trabajar con clases inmutables.

Anotaciones de bean

La siguiente tabla muestra las anotaciones de bean equivalentes para un caso de uso específico que se utilizan en V1 y V2. Se utiliza un escenario de clase de Customer para ilustrar parámetros.

Las anotaciones, así como las clases y las enumeraciones, de la V2 siguen la convención de mayúsculas y minúsculas en camello y utilizan “DynamoDb”, no “DynamoDB”.

Caso de uso V1 V2
Asignar clase a tabla
@DynamoDBTable (tableName ="CustomerTable")
@DynamoDbBean @DynamoDbBean(converterProviders = {...})
El nombre de la tabla se define al llamar al método DynamoDbEnhancedClient#table().
Designar un miembro de clase como atributo de tabla
@DynamoDBAttribute(attributeName = "customerName")
@DynamoDbAttribute("customerName")
Designar un miembro de clase como clave de hash/partición
@DynamoDBHashKey
@DynamoDbPartitionKey
Designar un miembro de clase como clave de rango/clasificación
@DynamoDBRangeKey
@DynamoDbSortKey
Designar un miembro de clase como clave de hash/partición de índice secundario
@DynamoDBIndexHashKey
@DynamoDbSecondaryPartitionKey
Designar un miembro de clase como clave de rango/clasificación de índice secundario
@DynamoDBIndexRangeKey
@DynamoDbSecondarySortKey
Ignorar este miembro de clase al asignarlo a una tabla
@DynamoDBIgnore
@DynamoDbIgnore
Designar un miembro de clase como atributo clave UUID generado automáticamente
@DynamoDBAutoGeneratedKey
@DynamoDbAutoGeneratedUuid

La extensión que lo proporciona no se carga de forma predeterminada; debe agregarla al compilador de clientes.

Designar un miembro de clase como atributo de marca de tiempo generado automáticamente
@DynamoDBAutoGeneratedTimestamp
@DynamoDbAutoGeneratedTimestampAttribute

La extensión que lo proporciona no se carga de forma predeterminada; debe agregarla al compilador de clientes.

Designar un miembro de clase como atributo de versión con incremento automático
@DynamoDBVersionAttribute
@DynamoDbVersionAttribute

La extensión que proporciona esto se carga automáticamente.

Designar que un miembro de clase requiere una conversión personalizada
@DynamoDBTypeConverted
@DynamoDbConvertedBy
Designar que un miembro de clase se almacene como otro tipo de atributo
@DynamoDBTyped(<DynamoDBAttributeType>)

Utilice una implementación de AttributeConverter. V2 proporciona muchos convertidores integrados para tipos de Java comunes. También puede implementar su propio AttributeConverter o AttributeConverterProvider personalizado. Consulte Conversión de atributos de control en esta guía.

Designe una clase que se pueda serializar en un documento (documento de estilo JSON) o subdocumento de DynamoDB
@DynamoDBDocument
Uso de la API de Documento mejorado Consulte los siguientes recursos:

Anotaciones adicionales de la V2

Caso de uso V1 V2
Designar que un miembro de clase no se almacene como atributo NULL si el valor de Java es nulo N/A
@DynamoDbIgnoreNulls
Designar un miembro de clase como objeto vacío si todos los atributos son nulos N/A
@DynamoDbPreserveEmptyObject
Designar una acción de actualización especial para un miembro de clase N/A
@DynamoDbUpdateBehavior
Designar una clase inmutable N/A
@DynamoDbImmutable
Designar un miembro de clase como atributo de contador de incremento automático N/A
@DynamoDbAtomicCounter

La extensión que proporciona esto se carga automáticamente.

Configuración

En la V1, generalmente se controlan comportamientos específicos mediante una instancia de DynamoDBMapperConfig. Puede proporcionar el objeto de configuración al crear el asignador o al realizar una solicitud. En la V2, la configuración es específica del objeto de solicitud de la operación.

Caso de uso V1 Predeterminado en V1 V2
DynamoDBMapperConfig.builder()
Estrategia de reintento de carga/escritura por lotes
.withBatchLoadRetryStrategy(loadRetryStrategy)
.withBatchWriteRetryStrategy(writeRetryStrategy)
reintento de elementos fallidos Configure la estrategia de reintento en el DynamoDBClient subyacente. Consulte Configuración del comportamiento de reintento en AWS SDK for Java 2.x en esta guía.
Lecturas consistentes
.withConsistentReads(CONSISTENT)
EVENTUAL De forma predeterminada, las lecturas consistentes son falsas para operaciones de lectura. Anule con .consistentRead(true) en el objeto de solicitud.
Esquema de conversión con conjuntos de serializadores/deserializadores
.withConversionSchema(conversionSchema)

Las implementaciones estáticas proporcionan compatibilidad con versiones anteriores.

V2_COMPATIBLE No se usa. Se trata de una función antigua que hace referencia a la forma en que las primeras versiones de DynamoDB (V1) almacenaban los tipos de datos, y este comportamiento no se conservará en el cliente mejorado. Un ejemplo de comportamiento en DynamoDB V1 es almacenar los valores booleanos como número en lugar de como booleanos.
Nombres de tablas
.withObjectTableNameResolver() .withTableNameOverride() .withTableNameResolver()

Las implementaciones estáticas proporcionan compatibilidad con versiones anteriores

usa anotación o estimación a partir de la clase

El nombre de la tabla se define al llamar al método DynamoDbEnhancedClient#table().

Estrategia de carga de paginación
.withPaginationLoadingStrategy(strategy)

Las opciones son: LAZY_, LOADING, EAGER_LOADING o ITERATION_ONLY

LAZY_LOADING
  • Iteración solo es la opción predeterminada. No se admiten las demás opciones de la V1.

  • Puede implementar el equivalente a una carga intensiva en la V2 con lo siguiente:

    List<Customer> allItems = customerTable.scan().items().stream().collect(Collectors.toList());
  • Para carga diferida, debe implementar su propia lógica de almacenamiento en caché para los elementos a los que acceda.

Solicitud de recopilación de métricas
.withRequestMetricCollector(collector)
null Use metricPublisher() en ClientOverrideConfiguration al crear el cliente estándar de DynamoDB.
Comportamiento de guardado
.withSaveBehavior(SaveBehavior.CLOBBER)

Las opciones son UPDATE, CLOBBER, PUT, APPEND_SET o UPDATE_SKIP_NULL_ATTRIBUTES.

UPDATE

En la V2, se llama a putItem() o updateItem() de forma explícita.

CLOBBER or PUT: la acción correspondiente en la v2 es llamar a putItem(). No hay una configuración específica de CLOBBER.

UPDATE: Corresponde con updateItem()

UPDATE_SKIP_NULL_ATTRIBUTES: Corresponde con updateItem(). Controle el comportamiento de actualización con la configuración de solicitud ignoreNulls y la anotación/etiqueta DynamoDbUpdateBehavior.

APPEND_SET: no se admite

Fábrica de convertidores de tipos
.withTypeConverterFactory(typeConverterFactory)
convertidores de tipos estándar

Establezca el bean utilizando

@DynamoDbBean(converterProviders = {ConverterProvider.class, DefaultAttributeConverterProvider.class})

Configuración por operación

En la V1, algunas operaciones, por ejemplo, query(), son altamente configurables mediante un objeto de “expresión” enviado a la operación. Por ejemplo:

DynamoDBQueryExpression<Customer> emailBwQueryExpr = new DynamoDBQueryExpression<Customer>() .withRangeKeyCondition("Email", new Condition() .withComparisonOperator(ComparisonOperator.BEGINS_WITH) .withAttributeValueList( new AttributeValue().withS("my"))); mapper.query(Customer.class, emailBwQueryExpr);

En la V2, en lugar de utilizar un objeto de configuración, se establecen parámetros en el objeto de solicitud mediante un generador. Por ejemplo:

QueryEnhancedRequest emailBw = QueryEnhancedRequest.builder() .queryConditional(QueryConditional .sortBeginsWith(kb -> kb .sortValue("my"))).build(); customerTable.query(emailBw);

Condicionales

En la V2, las expresiones condicionales y de filtrado se expresan mediante un objeto Expression, que encapsula la condición y la asignación de nombres y filtros.

Caso de uso Operaciones V1 V2
Condiciones de atributo esperadas save(), delete(), query(), scan()
new DynamoDBSaveExpression() .withExpected(Collections.singletonMap( "otherAttribute", new ExpectedAttributeValue(false))) .withConditionalOperator(ConditionalOperator.AND);
Obsoleto; utilice ConditionExpression en su lugar.
Expresión de condición delete()
deleteExpression.setConditionExpression("zipcode = :zipcode") deleteExpression.setExpressionAttributeValues(...)
Expression conditionExpression = Expression.builder() .expression("#key = :value OR #key1 = :value1") .putExpressionName("#key", "attribute") .putExpressionName("#key1", "attribute3") .putExpressionValue(":value", AttributeValues.stringValue("wrong")) .putExpressionValue(":value1", AttributeValues.stringValue("three")) .build(); DeleteItemEnhancedRequest request = DeleteItemEnhancedRequest.builder() .conditionExpression(conditionExpression).build();
Expresión de filtro query(), scan()
scanExpression .withFilterExpression("#statename = :state") .withExpressionAttributeValues(attributeValueMapBuilder.build()) .withExpressionAttributeNames(attributeNameMapBuilder.build())
Map<String, AttributeValue> values = singletonMap(":key", stringValue("value")); Expression filterExpression = Expression.builder() .expression("name = :key") .expressionValues(values) .build(); QueryEnhancedRequest request = QueryEnhancedRequest.builder() .filterExpression(filterExpression).build();
Expresión de condición para consulta query()
queryExpression.withKeyConditionExpression()
QueryConditional keyEqual = QueryConditional.keyEqualTo(b -> b .partitionValue("movie01")); QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder() .queryConditional(keyEqual) .build();

Conversión de tipos

Convertidores predeterminados

En la V2, el SDK proporciona un conjunto de convertidores predeterminados para todos los tipos comunes. Puede cambiar los convertidores de tipos tanto en el nivel de proveedor general como para un único atributo. Encontrará una lista de los convertidores disponibles en la referencia de la API AttributeConverter.

Establecimiento de un conversor personalizado para un atributo

En la V1, puede anotar un método getter con @DynamoDBTypeConverted para especificar la clase que convierte entre el tipo de atributo de Java y un tipo de atributo de DynamoDB. Por ejemplo, se puede aplicar un CurrencyFormatConverter que convierta entre un tipo Currency de Java y una cadena de DynamoDB, como se muestra en el siguiente fragmento de código.

@DynamoDBTypeConverted(converter = CurrencyFormatConverter.class) public Currency getCurrency() { return currency; }

A continuación se muestra el equivalente en V2 del fragmento anterior.

@DynamoDbConvertedBy(CurrencyFormatConverter.class) public Currency getCurrency() { return currency; }
nota

En la V1 puede aplicar la anotación al atributo en sí, a un tipo o a una anotación definida por el usuario, mientras que en la V2 solo se puede aplicar la anotación al getter.

Adición de una fábrica o un proveedor de convertidores de tipos

En la V1 puede proporcionar su propio conjunto de convertidores de tipos o anular los tipos que le interesen añadiendo una fábrica de convertidores de tipos a la configuración. La fábrica de convertidores de tipos amplía DynamoDBTypeConverterFactory y las anulaciones se realizan tomando una referencia al conjunto predeterminado y ampliándola. En el siguiente fragmento de código se muestra cómo hacerlo.

DynamoDBTypeConverterFactory typeConverterFactory = DynamoDBTypeConverterFactory.standard().override() .with(String.class, CustomBoolean.class, new DynamoDBTypeConverter<String, CustomBoolean>() { @Override public String convert(CustomBoolean bool) { return String.valueOf(bool.getValue()); } @Override public CustomBoolean unconvert(String string) { return new CustomBoolean(Boolean.valueOf(string)); }}).build(); DynamoDBMapperConfig config = DynamoDBMapperConfig.builder() .withTypeConverterFactory(typeConverterFactory) .build(); DynamoDBMapper mapperWithTypeConverterFactory = new DynamoDBMapper(dynamo, config);

La V2 proporciona una funcionalidad similar a través de la anotación @DynamoDbBean. Puede proporcionar un AttributeConverterProvider único o una cadena de AttributeConverterProvider en orden. Tenga en cuenta que si suministra su propia cadena de proveedores de convertidores de atributos, anulará el proveedor de convertidores predeterminado y deberá incluirlo en la cadena para utilizar sus convertidores de atributos.

@DynamoDbBean(converterProviders = { ConverterProvider1.class, ConverterProvider2.class, DefaultAttributeConverterProvider.class}) public class Customer { ... }

La sección sobre conversión de atributos de esta guía contiene un ejemplo completo para la V2.