Persistência de dados no Android com ROOM #2 — Mapeando Relacionamentos

Jefferson Tavares de Pádua
4 min readJun 22, 2018

--

Photo by Reptile Pod on Unsplash

Nessa postagem assumo que você já tenha compreendido como criar entidades utilizando Room. Acesse o link abaixo para mais informações:

Toda aplicação, seja de pequeno ou grande porte, sempre lida com mais de um tipo de informação. Caso esteja construindo um blog, por exemplo, “Postagem”, “Autor” e “Comentário” são algumas das informações que a sua aplicação deverá controlar.

Ao utilizar a biblioteca de persistência Room, esses grupos de informação são modelados em entidades, que posteriormente virão a ser persistidas em um banco de dados.

No entanto, é importante ter em mente que o Room não atua como um ORM (Object Relational Mapping), e por essa razão, a biblioteca não realiza a persistência automática de objetos aninhados nas suas Entidades, o que força o desenvolvedor a mapear os relacionamentos manualmente.

Relacionamento 1:N

Como o próprio nome indica, o relacionamento 1:N é aquele em que um registro na tabela A possui N registros na tabela B. Nessa linha de raciocínio, em um blog, um Autor possui inúmeras (n) Postagens.

Para mapear esse tipo de relacionamento, a tabela do lado N deve possuir um atributo do mesmo tipo da chave primária do lado 1, conforme o exemplo abaixo:

@Entity
data class Autor(
@PrimaryKey
val id: Int,
...
)

@Entity
data class Postagem(
@PrimaryKey
val id: Int
val autor: Int
...
)

Uma vez que o atributo é adicionado à entidade, basta indicar ao Room que esse atributo é uma chave estrangeira.

@Entity(foreignKeys = [
ForeignKey(
entity = Autor::class,
parentColumns = ["id"],
childColumns = ["autor")]
)
data class Postagem (...)

Pronto! Agora as entidades estão relacionadas. Agora vamos entender como funciona?!

Como você pode ver, o atributo “foreignKeys” é adicionado à anotação @Entity. Esse atributo recebe um array contendo todas as chaves estrangeiras especificadas na entidade.

Para mapear cada uma das chaves estrangeiras é utilizada a anotação ForeignKey, e os atributos entity, parentColumns e childColumns são preenchidos.

O atributo “entity” indica qual a entidade essa chave estrangeira se refere. Isso permitirá que o Room faça a verificação dos registros no momento da persistência, e garanta que a chave realmente exista na tabela.

Já os atributos “parentColumns” e “childColumns” servem para fazer o mapeamento bidirecional das colunas utilizadas no relacionamento.

As strings passadas em “parentColumns” devem apontar exatamente para os atributos utilizados para a formação da chave primária existente na classe apontada como “entity” (nesse caso apontamos para o atributo “id” contido na entidade “Autor”).

No mesmo sentido, as strings contidas em “childColumns” apontam para os atributos da entidade atual que formam o relacionamento (aqui apontamos para o atributo “autor” presente na entidade “Postagem”)

Relacionamento N:N

Para exemplificar como funciona um relacionamento N:N, imagine que agora os requisitos do blog que estamos desenvolvendo requerem que autores possam criar postagens compartilhadas. Isso fará com que uma postagem pertença a mais de um autor, e assim como antes, um autor possuirá mais de uma postagem, logo, a relação existente entre as tabelas é de N:N.

Para representar esse tipo de relacionamento com o Room, é necessário que criemos uma entidade alternativa, conforme o exemplo abaixo:

@Entity
data class AutorPostagem(
val autor: Int,
val postagem: Int
)

Feito isso, é necessário relacionar essa entidade com as entidades Autor e Postagem:

@Entity(
tableName = "autores_postagens",
primaryKeys = ["autor", "postagem"],
foreignKeys = [
ForeignKey(
entity = Autor::class,
parentColumns = ["id"],
childColumns = ["autor"]
),

ForeignKey(
entity = Postagem::class,
parentColumns = ["id"],
childColumns = ["postagem"]
)
]
)
data class AutorPostagem(...)

Ok, à primeira vista isso pode parecer assustador, mas vamos analisar por partes para que você possa perceber que é tudo bem simples.

Assim como antes, anotamos a classe com @Entity para que o Room possa reconhecê-la, porém dessa vez adicionamos o atributo “tableName”, que serve para modificar o nome da tabela que será criada de “AutorPostagem” (nome da classe) para “autores_postagens”.

Uma vez feito isso, o restante do código tem o mesmo significado daquele utilizado no relacionamento 1:N. A única diferença é que nesse caso, mapeamos duas chaves estrangeiras.

#Done

E isso é tudo o que você precisa para criar relacionamentos 1:N e N:N com o Room. A versão final do código ficaria assim:

Caso tenha gostado dessa postagem, não se esqueça de deixar alguns aplausos. Se quiser saber um pouco mais sobre essa biblioteca ou sobre desenvolvimento Android com Kotlin, é só me seguir para ser notificado sobre as próximas postagens.

Até a próxima.

--

--