Únete a ⁠ #Android11: The Beta Launch Show el 3 de junio.

Cómo definir datos con entidades Room

Cuando usas la biblioteca de persistencias Room, defines conjuntos de campos relacionados como entidades. Para cada entidad, se crea una tabla dentro del objeto Database asociado con el fin de retener los elementos. Debes hacer referencia a la clase de entidad mediante el arreglo de entities en la clase Database.

En el siguiente fragmento de código, se muestra cómo definir una entidad:

Kotlin

    @Entity
    data class User(
        @PrimaryKey var id: Int,
        var firstName: String?,
        var lastName: String?
    )
    

Java

    @Entity
    public class User {
        @PrimaryKey
        public int id;

        public String firstName;
        public String lastName;
    }
    

Para conservar un campo, Room debe tener acceso a él. Puedes hacer que un campo sea público o puedes proporcionarle un captador y un colocador. Si usas los métodos de captador y colocador, ten en cuenta que están basados en las convenciones de JavaBeans en Room.

Cómo usar una clave primaria

Cada entidad debe definir al menos 1 campo como clave primaria. Incluso cuando solo hay 1 campo, aún necesitas usar la anotación @PrimaryKey. Además, si quieres que Room asigne ID automáticos a entidades, puedes configurar la propiedad autoGenerate de @PrimaryKey. Si la entidad tiene una clave primaria compuesta, puedes usar la propiedad primaryKeys de la anotación @Entity, como se muestra en el siguiente fragmento de código:

Kotlin

    @Entity(primaryKeys = arrayOf("firstName", "lastName"))
    data class User(
        val firstName: String?,
        val lastName: String?
    )
    

Java

    @Entity(primaryKeys = {"firstName", "lastName"})
    public class User {
        public String firstName;
        public String lastName;
    }
    

De manera predeterminada, Room usa el nombre de la clase como el nombre de la tabla de la base de datos. Si quieres que la tabla tenga un nombre diferente, configura la propiedad tableName de la anotación @Entity, como se muestra en el siguiente fragmento de código:

Kotlin

    @Entity(tableName = "users")
    data class User (
        // ...
    )
    

Java

    @Entity(tableName = "users")
    public class User {
        // ...
    }
    

Precaución: En SQLite, los nombres de tabla no distinguen entre mayúsculas y minúsculas.

Al igual que la propiedad tableName, Room usa los nombres de campo como nombres de columna en la base de datos. Si quieres que una columna tenga un nombre diferente, agrega la anotación @ColumnInfo a un campo, como se muestra en el siguiente fragmento de código:

Kotlin

    @Entity(tableName = "users")
    data class User (
        @PrimaryKey val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?
    )
    

Java

    @Entity(tableName = "users")
    public class User {
        @PrimaryKey
        public int id;

        @ColumnInfo(name = "first_name")
        public String firstName;

        @ColumnInfo(name = "last_name")
        public String lastName;
    }
    

Cómo ignorar campos

De manera predeterminada, Room crea una columna para cada campo que se define en la entidad. Si una entidad tiene campos que no deseas conservar, puedes usar la anotación @Ignore en ellos, como se muestra en el siguiente fragmento de código:

Kotlin

    @Entity
    data class User(
        @PrimaryKey val id: Int,
        val firstName: String?,
        val lastName: String?,
        @Ignore val picture: Bitmap?
    )
    

Java

    @Entity
    public class User {
        @PrimaryKey
        public int id;

        public String firstName;
        public String lastName;

        @Ignore
        Bitmap picture;
    }
    

En los casos en que una entidad hereda campos de una entidad principal, suele ser más fácil usar la propiedad ignoredColumns del atributo @Entity:

Kotlin

    open class User {
        var picture: Bitmap? = null
    }

    @Entity(ignoredColumns = arrayOf("picture"))
    data class RemoteUser(
        @PrimaryKey val id: Int,
        val hasVpn: Boolean
    ) : User()
    

Java

    @Entity(ignoredColumns = "picture")
    public class RemoteUser extends User {
        @PrimaryKey
        public int id;

        public boolean hasVpn;
    }
    

Room admite varios tipos de anotaciones que facilitan la búsqueda de detalles en las tablas de la base de datos. Usa la búsqueda en el texto completo a menos que la versión de minSdkVersion de tu app sea inferior a 16.

Cómo admitir la búsqueda en el texto completo

Si tu app requiere un acceso muy rápido a la información de la base de datos mediante la búsqueda en el texto completo (FTS), respalda tus entidades mediante una tabla virtual que use el módulo de extensión SQLite FTS3 o FTS4. Para usar esta función, disponible en Room 2.1.0 y versiones posteriores, agrega la anotación @Fts3 o @Fts4 a una entidad dada, como se muestra en el siguiente fragmento de código:

Kotlin

    // Use `@Fts3` only if your app has strict disk space requirements or if you
    // require compatibility with an older SQLite version.
    @Fts4
    @Entity(tableName = "users")
    data class User(
        /* Specifying a primary key for an FTS-table-backed entity is optional, but
           if you include one, it must use this type and column name. */
        @PrimaryKey @ColumnInfo(name = "rowid") val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?
    )
    

Java

    // Use `@Fts3` only if your app has strict disk space requirements or if you
    // require compatibility with an older SQLite version.
    @Fts4
    @Entity(tableName = "users")
    public class User {
        // Specifying a primary key for an FTS-table-backed entity is optional, but
        // if you include one, it must use this type and column name.
        @PrimaryKey
        @ColumnInfo(name = "rowid")
        public int id;

        @ColumnInfo(name = "first_name")
        public String firstName;
    }
    

En los casos en que una tabla admita contenido en varios idiomas, usa la opción languageId para especificar la columna que almacena la información de idioma de cada fila:

Kotlin

    @Fts4(languageId = "lid")
    @Entity(tableName = "users")
    data class User(
        // ...
        @ColumnInfo(name = "lid") val languageId: Int
    )
    

Java

    @Fts4(languageId = "lid")
    @Entity(tableName = "users")
    public class User {
        // ...

        @ColumnInfo(name = "lid")
        int languageId;
    }
    

Room ofrece varias opciones para definir entidades respaldadas por FTS, como el orden de los resultados, los tipos de tokenizadores y las tablas administradas como contenido externo. Para obtener más información sobre estas opciones, consulta la referencia de FtsOptions.

Columnas específicas del índice

Si tu app debe admitir versiones de SDK que no permiten usar entidades respaldadas por tablas FTS3 o FTS4, puedes indexar ciertas columnas en la base de datos para agilizar tus consultas. Para agregar índices a una entidad, incluye la propiedad indices dentro de la anotación @Entity, enumerando los nombres de las columnas que deseas incluir en el índice o en el índice compuesto. En el siguiente fragmento de código, se muestra este proceso de anotación:

Kotlin

    @Entity(indices = arrayOf(Index(value = ["last_name", "address"])))
    data class User(
        @PrimaryKey val id: Int,
        val firstName: String?,
        val address: String?,
        @ColumnInfo(name = "last_name") val lastName: String?,
        @Ignore val picture: Bitmap?
    )
    

Java

    @Entity(indices = {@Index("name"),
            @Index(value = {"last_name", "address"})})
    public class User {
        @PrimaryKey
        public int id;

        public String firstName;
        public String address;

        @ColumnInfo(name = "last_name")
        public String lastName;

        @Ignore
        Bitmap picture;
    }
    

A veces, ciertos campos o grupos de campos de una base de datos deben ser únicos. Puedes aplicar esta propiedad de unicidad mediante la propiedad unique de una anotación @Index en true. En el siguiente ejemplo de código, se evita que una tabla tenga dos filas con el mismo conjunto de valores para las columnas firstName y lastName:

Kotlin

    @Entity(indices = arrayOf(Index(value = ["first_name", "last_name"],
            unique = true)))
    data class User(
        @PrimaryKey val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?,
        @Ignore var picture: Bitmap?
    )
    

Java

    @Entity(indices = {@Index(value = {"first_name", "last_name"},
            unique = true)})
    public class User {
        @PrimaryKey
        public int id;

        @ColumnInfo(name = "first_name")
        public String firstName;

        @ColumnInfo(name = "last_name")
        public String lastName;

        @Ignore
        Bitmap picture;
    }
    

Cómo incluir objetos basados en AutoValue

En la Room 2.1.0 y versiones posteriores, puedes usar clases de valores inmutables basadas en Java, que puedes anotar mediante @AutoValue, como entidades en la base de datos de tu app. Esta compatibilidad es particularmente útil cuando dos instancias de una entidad se consideran iguales si sus columnas contienen valores idénticos.

Cuando se usan clases anotadas con @AutoValue como entidades, puedes anotar los métodos abstractos de la clase mediante @PrimaryKey, @ColumnInfo, @Embedded y @Relation. Sin embargo, si usas estas anotaciones, debes incluir la anotación @CopyAnnotations cada vez, a fin de que Room pueda interpretar las implementaciones autogeneradas de los métodos correctamente.

En el siguiente fragmento de código, se muestra un ejemplo de una clase anotada con @AutoValue que Room reconoce como una entidad:

User.java

    @AutoValue
    @Entity
    public abstract class User {
        // Supported annotations must include `@CopyAnnotations`.
        @CopyAnnotations
        @PrimaryKey
        public abstract long getId();

        public abstract String getFirstName();
        public abstract String getLastName();

        // Room uses this factory method to create User objects.
        public static User create(long id, String firstName, String lastName) {
            return new AutoValue_User(id, firstName, lastName);
        }
    }