Nivelar atributos de outras classes - AWS SDK for Java 2.x

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Nivelar atributos de outras classes

Se os atributos da sua tabela estiverem espalhados por várias classes Java diferentes, seja por herança ou composição, o DynamoDB Enhanced Client API fornecerá suporte para nivelar os atributos em uma classe.

Usar herança

Se suas classes usam herança, use as seguintes abordagens para nivelar a hierarquia.

Usar beans anotados

Para a abordagem de anotação, ambas as classes devem conter a anotação @DynamoDbBean e uma classe deve conter uma ou mais anotações de chave primária.

Veja a seguir exemplos de classes de dados que têm uma relação de herança.

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

A opção onMethod do Lombok copia anotações do DynamoDB baseadas em atributos, como @DynamoDbPartitionKey, no código gerado.

@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 a abordagem do esquema estático, use o método extend() do construtor para reduzir os atributos da classe principal para a classe secundária. Isso é mostrado depois da linha de comentário 1 no seguinte exemplo:

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

O exemplo anterior do esquema estático usa as seguintes classes de dados: Uma vez que o mapeamento é definido quando você cria o esquema de tabela estática, as classes de dados não exigem anotações.

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; }

Usar composição

Se suas classes usam composição, use as seguintes abordagens para nivelar a hierarquia.

Usar beans anotados

A anotação @DynamoDbFlatten nivela a classe contida.

Os exemplos de classes de dados a seguir usam a anotação @DynamoDbFlatten para adicionar efetivamente todos os atributos da classe GenericRecord contida à classe 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; }

Você pode usar a anotação de nivelamento para nivelar quantas classes elegíveis forem necessárias. As limitações a seguir aplicam-se:

  • Todos os nomes de atributos devem ser exclusivos depois de serem nivelados.

  • Nunca deve haver mais de uma chave de partição, chave de classificação ou nome de tabela.

Usar esquemas estáticos

Ao criar um esquema de tabela estático, use o método flatten() do construtor. Você também fornece os métodos getter e setter que identificam a classe contida.

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

O exemplo anterior do esquema estático usa as seguintes classes de dados:

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; }

Você pode usar o padrão do construtor para nivelar quantas classes elegíveis forem necessárias.

Implicações para outro código

Quando você usa o atributo @DynamoDbFlatten (ou método flatten() do construtor), o item no DynamoDB contém um atributo para cada atributo do objeto composto. Isso também inclui os atributos do objeto de composição.

Por outro lado, se você anotar uma classe de dados com uma classe composta e não usar @DynamoDbFlatten, o item será salvo com o objeto composto como um único atributo.

Por exemplo, compare a classe Customer mostrada no exemplo de nivelamento com composição com e sem nivelamento do atributo record. Você pode visualizar a diferença JSON conforme mostrado na tabela a seguir.

Com nivelamento Sem nivelamento
3 atributos 2 atributos
{ "id": "1", "createdDate": "today", "name": "my name" }
{ "id": "1", "record": { "createdDate": "today", "name": "my name" } }

A diferença se torna importante se você tiver outro código acessando a tabela do DynamoDB que espera encontrar certos atributos.