Persistência de dados no Android com ROOM #2 — Mapeando Relacionamentos
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.