Definir e consultar relações de um para muitos

Uma relação de um para muitos entre duas entidades é uma relação em que cada instância da entidade pai corresponde a zero ou mais instâncias da entidade filha, mas cada instância da entidade filha só pode corresponder exatamente a uma instância da entidade pai.

No exemplo do app de streaming de música, suponha que o usuário consiga organizar as músicas em playlists. Cada usuário pode criar quantas playlists quiser, mas cada playlist é criada por exatamente um usuário. Portanto, há uma relação de um para muitos entre a entidade User e a entidade Playlist.

Siga estas etapas para definir e consultar relações de um para muitos no seu banco de dados:

  1. Defina a relação: crie classes para as duas entidades, com a entidade filha fazendo referência à chave primária da entidade pai.
  2. Consulte as entidades: modele a relação em uma nova classe de dados e implemente uma função para recuperar os dados relacionados.

Definir a relação

Para definir uma relação de um para muitos, crie uma classe para cada entidade. Como nas relações um para um, a entidade filha precisa incluir uma variável que faça referência à chave primária da entidade pai.

@Entity
data class User(
    @PrimaryKey val userId: Long,
    val name: String,
    val age: Int
)

@Entity
data class Playlist(
    @PrimaryKey val playlistId: Long,
    val userCreatorId: Long,
    val playlistName: String
)

Consultar as entidades

Para consultar a lista de usuários e playlists correspondentes, é necessário modelar a relação um para muitos entre as duas entidades.

Para modelar a relação, crie uma nova classe de dados. Cada instância dessa classe contém uma instância da entidade pai e uma lista de todas as instâncias de entidade filha correspondentes. Adicione a @Relation anotação à propriedade que representa a lista de entidades filhas. Defina parentColumns como o nome da coluna de chave primária da entidade pai e defina entityColumns como o nome da coluna da entidade filha que faz referência à chave primária da entidade pai.

data class UserWithPlaylists(
    @Embedded val user: User,
    @Relation(
        parentColumns = ["userId"],
        entityColumns = ["userCreatorId"]
    )
    val playlists: List<Playlist>
)

Por fim, adicione uma função à classe de objeto de acesso a dados (DAO, na sigla em inglês) que retorna todas as instâncias da classe de dados que emparelha a entidade pai e a entidade filha. Adicione a anotação @Transaction para que o Room execute toda a operação atomicamente. Essa anotação é necessária porque a função exige que o Room execute duas consultas.

@Transaction
@Query("SELECT * FROM User")
suspend fun getUsersWithPlaylists(): List<UserWithPlaylists>

Chaves compostas

Se você definir a relação usando chaves compostas, especifique várias colunas em parentColumns e entityColumns. A ordem das colunas em parentColumns precisa corresponder à ordem das colunas em entityColumns.

@Entity(primaryKeys = ["firstName", "lastName"])
data class User(
    val firstName: String,
    val lastName: String,
    val age: Int
)

@Entity
data class Playlist(
    @PrimaryKey val playlistId: Long,
    val userFirstName: String,
    val userLastName: String,
    val playlistName: String
)

data class UserWithPlaylists(
    @Embedded val user: User,
    @Relation(
        parentColumns = ["firstName", "lastName"],
        entityColumns = ["userFirstName", "userLastName"]
    )
    val playlists: List<Playlist>
)