Acceder a los atributos mejorados del documento como objetos personalizados - 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.

Acceder a los atributos mejorados del documento como objetos personalizados

Además de proporcionar una API para leer y escribir atributos con estructuras sin esquema, la API de documentos mejorada te permite convertir atributos desde y hacia instancias de clases personalizadas.

La API del cliente mejorado utiliza AttributeConverterProviders y AttributeConverters que se mostraron en la sección de conversión de atributos de control como parte de la API del cliente mejorado de DynamoDB.

En el ejemplo siguiente, utilizamos a CustomAttributeConverterProvider con su clase AddressConverter anidada para convertir objetos Address.

En este ejemplo se muestra que se pueden mezclar datos de clases y también datos de estructuras que se crean según sea necesario. En este ejemplo también se muestra que las clases personalizadas se pueden utilizar en cualquier nivel de una estructura anidada. Los objetos Address de este ejemplo son valores que se utilizan en un mapa.

public static void attributeToAddressClassMappingExample(DynamoDbEnhancedClient enhancedClient, DynamoDbClient standardClient) { String tableName = "customer"; // Define the DynamoDbTable for an enhanced document. // The schema builder provides methods for attribute converter providers and keys. DynamoDbTable<EnhancedDocument> documentDynamoDbTable = enhancedClient.table(tableName, DocumentTableSchema.builder() // Add the CustomAttributeConverterProvider along with the default when you build the table schema. .attributeConverterProviders( List.of( new CustomAttributeConverterProvider(), AttributeConverterProvider.defaultProvider())) .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", AttributeValueType.N) .addIndexSortKey(TableMetadata.primaryIndexName(), "lastName", AttributeValueType.S) .build()); // Create the DynamoDB table if needed. documentDynamoDbTable.createTable(); waitForTableCreation(tableName, standardClient); // The getAddressesForCustomMappingExample() helper method that provides 'addresses' shows the use of a custom Address class // rather than using a Map<String, Map<String, String> to hold the address data. Map<String, Address> addresses = getAddressesForCustomMappingExample(); // Build an EnhancedDocument instance to save an item with a mix of structures defined as needed and static classes. EnhancedDocument personDocument = EnhancedDocument.builder() .putNumber("id", 50) .putString("firstName", "Shirley") .putString("lastName", "Rodriguez") .putNumber("age", 53) .putNull("nullAttribute") .putJson("phoneNumbers", phoneNumbersJSONString()) // Note the use of 'EnhancedType.of(Address.class)' instead of the more generic // 'EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(String.class))' that was used in a previous example. .putMap("addresses", addresses, EnhancedType.of(String.class), EnhancedType.of(Address.class)) .putList("hobbies", List.of("Hobby 1", "Hobby 2"), EnhancedType.of(String.class)) .build(); // Save the item to DynamoDB. documentDynamoDbTable.putItem(personDocument); // Retrieve the item just saved. EnhancedDocument srPerson = documentDynamoDbTable.getItem(Key.builder().partitionValue(50).sortValue("Rodriguez").build()); // Access the addresses attribute. Map<String, Address> srAddresses = srPerson.get("addresses", EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(Address.class))); srAddresses.keySet().forEach(k -> logger.info(addresses.get(k).toString())); documentDynamoDbTable.deleteTable(); // The content logged to the console shows that the saved maps were converted to Address instances. Address{street='123 Main Street', city='Any Town', state='NC', zipCode='00000'} Address{street='100 Any Street', city='Any Town', state='NC', zipCode='00000'}
public class CustomAttributeConverterProvider implements AttributeConverterProvider { private final Map<EnhancedType<?>, AttributeConverter<?>> converterCache = ImmutableMap.of( // 1. Add AddressConverter to the internal cache. EnhancedType.of(Address.class), new AddressConverter()); public static CustomAttributeConverterProvider create() { return new CustomAttributeConverterProvider(); } // 2. The enhanced client queries the provider for attribute converters if it // encounters a type that it does not know how to convert. @SuppressWarnings("unchecked") @Override public <T> AttributeConverter<T> converterFor(EnhancedType<T> enhancedType) { return (AttributeConverter<T>) converterCache.get(enhancedType); } // 3. Custom attribute converter private class AddressConverter implements AttributeConverter<Address> { // 4. Transform an Address object into a DynamoDB map. @Override public AttributeValue transformFrom(Address address) { Map<String, AttributeValue> attributeValueMap = Map.of( "street", AttributeValue.fromS(address.getStreet()), "city", AttributeValue.fromS(address.getCity()), "state", AttributeValue.fromS(address.getState()), "zipCode", AttributeValue.fromS(address.getZipCode())); return AttributeValue.fromM(attributeValueMap); } // 5. Transform the DynamoDB map attribute to an Address oject. @Override public Address transformTo(AttributeValue attributeValue) { Map<String, AttributeValue> m = attributeValue.m(); Address address = new Address(); address.setStreet(m.get("street").s()); address.setCity(m.get("city").s()); address.setState(m.get("state").s()); address.setZipCode(m.get("zipCode").s()); return address; } @Override public EnhancedType<Address> type() { return EnhancedType.of(Address.class); } @Override public AttributeValueType attributeValueType() { return AttributeValueType.M; } } }
public class Address { private String street; private String city; private String state; private String zipCode; public Address() { } public String getStreet() { return this.street; } public String getCity() { return this.city; } public String getState() { return this.state; } public String getZipCode() { return this.zipCode; } public void setStreet(String street) { this.street = street; } public void setCity(String city) { this.city = city; } public void setState(String state) { this.state = state; } public void setZipCode(String zipCode) { this.zipCode = zipCode; } }

El siguiente método auxiliar proporciona el mapa que utiliza instancias Address personalizadas para los valores en lugar de instancias Map<String, String> genéricas para los valores.

private static Map<String, Address> getAddressesForCustomMappingExample() { Address homeAddress = new Address(); homeAddress.setStreet("100 Any Street"); homeAddress.setCity("Any Town"); homeAddress.setState("NC"); homeAddress.setZipCode("00000"); Address workAddress = new Address(); workAddress.setStreet("123 Main Street"); workAddress.setCity("Any Town"); workAddress.setState("NC"); workAddress.setZipCode("00000"); return Map.of("home", homeAddress, "work", workAddress); }