Ao usar a biblioteca de persistência do Room para armazenar os dados do app, você define entidades para representar os objetos que quer armazenar. Cada entidade corresponde a uma tabela no banco de dados associado do Room, e cada instância de uma entidade representa uma linha de dados na tabela correspondente.
Isso significa que é possível usar entidades do Room para definir o esquema do banco de dados (link em inglês) sem que seja necessário programar nenhum código SQL.
Anatomia de uma entidade
Defina cada entidade do Room como uma classe anotada com
@Entity
. Uma entidade do Room inclui
campos para cada coluna na tabela correspondente no banco de dados, incluindo uma
ou mais colunas que compõem a chave primária.
O código abaixo é um exemplo de entidade simples que define uma tabela User
com colunas de documento de identificação, nome e sobrenome:
Kotlin
@Entity data class User( @PrimaryKey val id: Int, val firstName: String?, val lastName: String? )
Java
@Entity public class User { @PrimaryKey public int id; public String firstName; public String lastName; }
Por padrão, o Room usa o nome da classe como nome da tabela do banco de dados. Se você quiser que
a tabela tenha um nome diferente, defina a
propriedade tableName
da anotação
@Entity
. Da mesma forma, por padrão, o Room usa os nomes dos campos como nomes de colunas no
banco de dados. Caso queira que uma coluna tenha um nome diferente, adicione a anotação
@ColumnInfo
ao
campo e defina a propriedade
name
. O exemplo a seguir demonstra nomes personalizados para uma tabela e as colunas:
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; }
Definir uma chave primária
Cada entidade do Room precisa definir uma chave
primária (link em inglês) que identifique cada linha de maneira exclusiva na tabela do banco de dados correspondente. A maneira
mais simples de fazer isso é adicionando a anotação
@PrimaryKey
a uma única coluna:
Kotlin
@PrimaryKey val id: Int
Java
@PrimaryKey public int id;
Definir uma chave primária composta
Caso precise que as instâncias de uma entidade sejam identificadas de maneira exclusiva por uma combinação
de várias colunas, defina uma chave primária composta listando essas
colunas na propriedade
primaryKeys
de
@Entity
:
Kotlin
@Entity(primaryKeys = ["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; }
Ignorar campos
Por padrão, o Room cria uma coluna para cada campo definido na entidade.
Se uma entidade tem campos que você não quer persistir, é possível adicionar a anotação
@Ignore
a esses campos, conforme
mostrado no snippet de código abaixo:
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; }
Em casos em que uma entidade herda campos de uma entidade pai, geralmente é
mais fácil usar a propriedade
ignoredColumns
do
atributo @Entity
:
Kotlin
open class User { var picture: Bitmap? = null } @Entity(ignoredColumns = ["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; }
Oferecer suporte a pesquisa em tabelas
O Room oferece suporte a vários tipos de anotações que facilitam a pesquisa
de detalhes nas tabelas do banco de dados. A menos que a minSdkVersion
do app seja anterior à 16,
use a pesquisa de texto completo.
Suporte a pesquisa de texto completo
Caso o app precise de acesso rápido a informações do banco de dados usando a pesquisa de
texto completo (FTS, na sigla em inglês), faça com que as entidades tenham uma tabela virtual que use o
módulo de extensão
FTS3 ou FTS4 do SQLite (link em inglês). Para usar esse recurso,
disponível no Room 2.1.0 e versões mais recentes, adicione a anotação
@Fts3
ou
@Fts4
a uma entidade, como
mostrado no snippet de código abaixo:
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; }
Em casos em que uma tabela é oferece suporte a conteúdo em vários idiomas, use a
opção languageId
para especificar a coluna que armazena informações de idioma de
cada linha:
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; }
O Room oferece várias outras opções para definir entidades com apoio do FTS, incluindo
ordenação de resultados, tipos de tokenizadores e tabelas gerenciadas como conteúdo externo. Para
ver mais detalhes sobre essas opções, consulte a referência
FtsOptions
.
Indexar colunas específicas
Se o app precisa oferecer suporte a versões do SDK que não têm suporte para o uso de entidades com tabelas compatíveis com FTS3- ou
FTS4, ainda é possível indexar colunas específicas no banco de dados
para acelerar as consultas. Para adicionar índices a uma entidade, inclua a propriedade
indices
na anotação
@Entity
,
listando os nomes das colunas que você quer incluir no índice simples
ou composto. O snippet de código abaixo demonstra esse processo de
anotação:
Kotlin
@Entity(indices = [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; }
Às vezes, alguns campos ou grupos de campos em um banco de dados precisam ser exclusivos.
Para aplicar essa exclusividade, defina a propriedade
unique
de uma anotação @Index
como true
. O exemplo de código abaixo impede que uma tabela tenha
duas linhas que contenham o mesmo conjunto de valores para as colunas firstName
e
lastName
:
Kotlin
@Entity(indices = [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; }
Incluir objetos baseados em AutoValue
No Room 2.1.0 e versões mais recentes, é possível usar classes de valor
imutável
(link em inglês) baseadas em Java, com a anotação @AutoValue
, como entidades no banco de dados do app. Esse
suporte é especialmente útil quando duas instâncias de uma entidade são consideradas
iguais caso as colunas tenham valores idênticos.
Ao usar classes com a anotação @AutoValue
como entidades, você pode adicionar anotações
aos métodos abstratos da classe com @PrimaryKey
, @ColumnInfo
, @Embedded
e
@Relation
. Contudo, ao usar essas anotações, é necessário incluir a
anotação @CopyAnnotations
todas as vezes, para que o Room possa interpretar corretamente as implementações do método
geradas de modo automático.
O snippet de código abaixo mostra um exemplo de uma classe com a anotação
@AutoValue
que o Room reconhece como uma entidade:
@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); } }