

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.

# Trabajar con clases de datos inmutables
<a name="ddb-en-client-use-immut"></a>

La característica de asignación de la API de cliente mejorado de DynamoDB funciona con clases de datos inmutables. Una clase inmutable solo tiene getters y requiere una clase constructora que el SDK utiliza para crear instancias de la clase. En lugar de usar la anotación `@DynamoDbBean` como se muestra en la [clase Customer](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust), las clases inmutables usan la anotación `@DynamoDbImmutable`, que toma un parámetro que indica la clase de generador que se va a usar.

La siguiente clase es una versión inmutable de `Customer`.

```
package org.example.tests.model.immutable;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.time.Instant;

@DynamoDbImmutable(builder = CustomerImmutable.Builder.class)
public class CustomerImmutable {
    private final String id;
    private final String name;
    private final String email;
    private final Instant regDate;

    private CustomerImmutable(Builder b) {
        this.id = b.id;
        this.email = b.email;
        this.name = b.name;
        this.regDate = b.regDate;
    }

    // This method will be automatically discovered and used by the TableSchema.
    public static Builder builder() { return new Builder(); }

    @DynamoDbPartitionKey
    public String id() { return this.id; }

    @DynamoDbSortKey
    public String email() { return this.email; }

    @DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name")
    public String name() { return this.name; }

    @DynamoDbSecondarySortKey(indexNames = {"customers_by_date", "customers_by_name"})
    public Instant regDate() { return this.regDate; }

    public static final class Builder {
        private String id;
        private String email;
        private String name;
        private Instant regDate;

        // The private Builder constructor is visible to the enclosing CustomerImmutable class.
        private Builder() {}

        public Builder id(String id) { this.id = id; return this; }
        public Builder email(String email) { this.email = email; return this; }
        public Builder name(String name) { this.name = name; return this; }
        public Builder regDate(Instant regDate) { this.regDate = regDate; return this; }

        // This method will be automatically discovered and used by the TableSchema.
        public CustomerImmutable build() { return new CustomerImmutable(this); }
    }
}
```

Debe cumplir los siguientes requisitos al anotar una clase de datos con `@DynamoDbImmutable`.

1. Todo método que no sea una sustitución de `Object.class` y que no haya sido anotado con `@DynamoDbIgnore` debe ser un método de obtención de un atributo de la tabla de DynamoDB.

1. Cada getter debe tener un setter correspondiente que distinga entre mayúsculas y minúsculas en la clase de constructor.

1. Solo debe cumplirse una de las siguientes condiciones de construcción.
   + La clase de constructor debe tener un constructor público predeterminado.
   + La clase de datos debe tener un nombre de método estático público `builder()` que no tome parámetros y devuelva una instancia de clase constructor. Esta opción se muestra en la clase `Customer` inmutable.

1.  La clase del constructor debe tener un método público llamado `build()` que no acepte parámetros y devuelva una instancia de la clase inmutable. 

Para crear un `TableSchema` para su clase inmutable, utilice el método `fromImmutableClass()` en `TableSchema` como se muestra en el siguiente fragmento.

```
static final TableSchema<CustomerImmutable> customerImmutableTableSchema = 
                         TableSchema.fromImmutableClass(CustomerImmutable.class);
```

Del mismo modo que puede crear una tabla de DynamoDB a partir de una clase mutable, también puede crear una a partir de una clase inmutable con una *llamada única* a `createTable()` de `DynamoDbTable` como se muestra en el siguiente ejemplo de fragmento.

```
static void createTableFromImmutable(DynamoDbEnhancedClient enhancedClient, String tableName, DynamoDbWaiter waiter){
    // First, create an in-memory representation of the table using the 'table()' method of the DynamoDb Enhanced Client.
    // 'table()' accepts a name for the table and a TableSchema instance that you created previously.
    DynamoDbTable<CustomerImmutable> customerDynamoDbTable = enhancedClient
            .table(tableName, TableSchema.fromImmutableClass(CustomerImmutable.class));
        
    // Second, call the 'createTable()' method on the DynamoDbTable instance.
    customerDynamoDbTable.createTable();
    waiter.waitUntilTableExists(b -> b.tableName(tableName));
}
```

## Utilizar bibliotecas de terceros, como Lombok
<a name="ddb-en-client-use-immut-lombok"></a>

Las bibliotecas de terceros, como [Project Lombok](https://projectlombok.org/), ayudan a generar código reutilizable asociado a objetos inmutables. La API de cliente mejorado de DynamoDB funciona con estas bibliotecas siempre que las clases de datos sigan las convenciones detalladas en esta sección. 

En el siguiente ejemplo, se muestra la clase `CustomerImmutable` inmutable con anotaciones de Lombok. Observe cómo la característica `onMethod` de Lombok copia las anotaciones de DynamoDB basadas en atributos, como `@DynamoDbPartitionKey`, en el código generado.

```
@Value
@Builder
@DynamoDbImmutable(builder = Customer.CustomerBuilder.class)
public class Customer {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;

    @Getter(onMethod_=@DynamoDbSortKey)
    private String email;

    @Getter(onMethod_=@DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name"))
    private String name;

    @Getter(onMethod_=@DynamoDbSecondarySortKey(indexNames = {"customers_by_date", "customers_by_name"}))
    private Instant createdDate;
}
```