Aplanar atributos de otras clases - 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.

Aplanar atributos de otras clases

Si los atributos de la tabla se distribuyen en varias clases de Java diferentes, ya sea por herencia o composición, el API cliente mejorado de DynamoDB permite agrupar los atributos en una sola clase.

Utilizar la herencia

Si sus clases utilizan herencias, utilice los siguientes enfoques para aplanar la jerarquía.

Utilizar objetos bean anotados

Para el método de anotación, ambas clases deben llevar la anotación @DynamoDbBean y una de ellas llevar una o más anotaciones de clave principal.

A continuación, se muestran ejemplos de clases de datos que tienen una relación de herencia.

Standard data class
@DynamoDbBean public class Customer extends GenericRecord { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } @DynamoDbBean public abstract class GenericRecord { private String id; private String createdDate; @DynamoDbPartitionKey public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCreatedDate() { return createdDate; } public void setCreatedDate(String createdDate) { this.createdDate = createdDate; } }
Lombok

La opción onMethod de Lombok copia anotaciones de DynamoDB basadas en atributos, como @DynamoDbPartitionKey, en el código generado.

@DynamoDbBean @Data @ToString(callSuper = true) public class Customer extends GenericRecord { private String name; } @Data @DynamoDbBean public abstract class GenericRecord { @Getter(onMethod_=@DynamoDbPartitionKey) private String id; private String createdDate; }

Usar esquemas estáticos

Para el enfoque de esquema estático, utilice el método extend() del generador para contraer los atributos de la clase principal en la clase secundaria. Esto se muestra después de la línea de comentario 1 en el siguiente ejemplo.

StaticTableSchema<org.example.tests.model.inheritance.stat.GenericRecord> GENERIC_RECORD_SCHEMA = StaticTableSchema.builder(org.example.tests.model.inheritance.stat.GenericRecord.class) // The partition key will be inherited by the top level mapper. .addAttribute(String.class, a -> a.name("id") .getter(org.example.tests.model.inheritance.stat.GenericRecord::getId) .setter(org.example.tests.model.inheritance.stat.GenericRecord::setId) .tags(primaryPartitionKey())) .addAttribute(String.class, a -> a.name("created_date") .getter(org.example.tests.model.inheritance.stat.GenericRecord::getCreatedDate) .setter(org.example.tests.model.inheritance.stat.GenericRecord::setCreatedDate)) .build(); StaticTableSchema<org.example.tests.model.inheritance.stat.Customer> CUSTOMER_SCHEMA = StaticTableSchema.builder(org.example.tests.model.inheritance.stat.Customer.class) .newItemSupplier(org.example.tests.model.inheritance.stat.Customer::new) .addAttribute(String.class, a -> a.name("name") .getter(org.example.tests.model.inheritance.stat.Customer::getName) .setter(org.example.tests.model.inheritance.stat.Customer::setName)) // 1. Use the extend() method to collapse the parent attributes onto the child class. .extend(GENERIC_RECORD_SCHEMA) // All the attributes of the GenericRecord schema are added to Customer. .build();

El ejemplo de esquema estático anterior utiliza las siguientes clases de datos. Dado que la asignación se define cuando se construye el esquema estático de la tabla, las clases de datos no requieren anotaciones.

Standard data class
public class Customer extends GenericRecord { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public abstract class GenericRecord { private String id; private String createdDate; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCreatedDate() { return createdDate; } public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
Lombok
@Data @ToString(callSuper = true) public class Customer extends GenericRecord{ private String name; } @Data public abstract class GenericRecord { private String id; private String createdDate; }

Utilizar composiciones

Si sus clases utilizan composiciones, siga los siguientes planteamientos para aplanar la jerarquía.

Utilizar objetos bean anotados

La anotación @DynamoDbFlatten aplana la clase contenida.

Los siguientes ejemplos de clases de datos utilizan la anotación @DynamoDbFlatten para añadir de forma eficaz todos los atributos de la clase GenericRecord contenida a la clase Customer.

Standard data class
@DynamoDbBean public class Customer { private String name; private GenericRecord record; public String getName() { return this.name; } public void setName(String name) { this.name = name; } @DynamoDbFlatten public GenericRecord getRecord() { return this.record; } public void setRecord(GenericRecord record) { this.record = record; } @DynamoDbBean public class GenericRecord { private String id; private String createdDate; @DynamoDbPartitionKey public String getId() { return this.id; } public void setId(String id) { this.id = id; } public String getCreatedDate() { return this.createdDate; } public void setCreatedDate(String createdDate) { this.createdDate = createdDate; } }
Lombok
@Data @DynamoDbBean public class Customer { private String name; @Getter(onMethod_=@DynamoDbFlatten) private GenericRecord record; } @Data @DynamoDbBean public class GenericRecord { @Getter(onMethod_=@DynamoDbPartitionKey) private String id; private String createdDate; }

Puede utilizar la anotación aplanar para aplanar tantas clases elegibles diferentes como necesite. Existen las siguientes limitaciones:

  • Después de ser aplanados, todos los nombres de atributos deben ser únicos.

  • Nunca debe haber más de una clave de partición, clave de clasificación o nombre de tabla.

Usar esquemas estáticos

Cuando construya un esquema de tabla estático, utilice el método flatten() del constructor. También debe suministrar los métodos getter y setter que identifican la clase contenida.

StaticTableSchema<GenericRecord> GENERIC_RECORD_SCHEMA = StaticTableSchema.builder(GenericRecord.class) .newItemSupplier(GenericRecord::new) .addAttribute(String.class, a -> a.name("id") .getter(GenericRecord::getId) .setter(GenericRecord::setId) .tags(primaryPartitionKey())) .addAttribute(String.class, a -> a.name("created_date") .getter(GenericRecord::getCreatedDate) .setter(GenericRecord::setCreatedDate)) .build(); StaticTableSchema<Customer> CUSTOMER_SCHEMA = StaticTableSchema.builder(Customer.class) .newItemSupplier(Customer::new) .addAttribute(String.class, a -> a.name("name") .getter(Customer::getName) .setter(Customer::setName)) // Because we are flattening a component object, we supply a getter and setter so the // mapper knows how to access it. .flatten(GENERIC_RECORD_SCHEMA, Customer::getRecord, Customer::setRecord) .build();

El ejemplo de esquema estático anterior utiliza las siguientes clases de datos.

Standard data class
public class Customer { private String name; private GenericRecord record; public String getName() { return this.name; } public void setName(String name) { this.name = name; } public GenericRecord getRecord() { return this.record; } public void setRecord(GenericRecord record) { this.record = record; } public class GenericRecord { private String id; private String createdDate; public String getId() { return this.id; } public void setId(String id) { this.id = id; } public String getCreatedDate() { return this.createdDate; } public void setCreatedDate(String createdDate) { this.createdDate = createdDate; } }
Lombok
@Data public class Customer { private String name; private GenericRecord record; } @Data public class GenericRecord { private String id; private String createdDate; }

Puede utilizar el patrón constructor para aplanar tantas clases elegibles diferentes como necesite.

Implicaciones para otro código

Cuando se utiliza el atributo @DynamoDbFlatten (o el método constructor flatten()), el elemento en DynamoDB contiene un atributo para cada atributo del objeto compuesto. También incluye los atributos del objeto que lo compone.

Por el contrario, si anota una clase de datos con una clase compuesta y no usa @DynamoDbFlatten, el elemento se guarda con el objeto compuesto como un atributo único.

Por ejemplo, compare la clase Customer que se muestra en el ejemplo de aplanamiento con composición con y sin aplanamiento del atributo record. Puede visualizar la diferencia JSON como se muestra en la siguiente tabla.

Con aplanamiento Con aplanamiento
3 atributos 2 atributos
{ "id": "1", "createdDate": "today", "name": "my name" }
{ "id": "1", "record": { "createdDate": "today", "name": "my name" } }

La diferencia es importante si hay otro código que accede a la tabla de DynamoDB y espera encontrar determinados atributos.