Определение и запрос отношений «один ко многим»

Отношение «один ко многим» между двумя сущностями — это отношение, при котором каждому экземпляру родительской сущности соответствует ноль или более экземпляров дочерней сущности, но каждому экземпляру дочерней сущности может соответствовать только один экземпляр родительской сущности.

В примере с приложением для потоковой передачи музыки предположим, что пользователь может организовывать свои песни в плейлисты. Каждый пользователь может создать столько плейлистов, сколько захочет, но каждый плейлист создаст ровно один пользователь. Следовательно, существует отношение «один ко многим» между сущностью User и сущностью Playlist .

Выполните следующие шаги, чтобы определить и запросить связи «один ко многим» в вашей базе данных:

  1. Определите взаимосвязь : создайте классы для обеих сущностей, при этом дочерняя сущность будет ссылаться на первичный ключ родительской сущности.
  2. Запрос к сущностям : Смоделируйте взаимосвязь в новом классе данных и реализуйте функцию для получения связанных данных.

Определите взаимоотношения

Для определения отношения «один ко многим» сначала создайте класс для каждой сущности. Как и в отношении «один к одному», дочерняя сущность должна содержать переменную, которая ссылается на первичный ключ родительской сущности.

@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
)

Запрос к сущностям

Для получения списка пользователей и соответствующих плейлистов необходимо сначала смоделировать отношение «один ко многим» между этими двумя сущностями.

Для моделирования связи создайте новый класс данных. Каждый экземпляр этого класса содержит экземпляр родительской сущности и список всех соответствующих экземпляров дочерних сущностей. Добавьте аннотацию @Relation к свойству, представляющему список дочерних сущностей. Установите parentColumns равным имени столбца первичного ключа родительской сущности, а entityColumns — имени столбца дочерней сущности, ссылающегося на первичный ключ родительской сущности.

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

Наконец, добавьте в класс объекта доступа к данным (DAO) функцию, которая возвращает все экземпляры класса данных, связывающие родительскую и дочернюю сущности. Добавьте аннотацию @Transaction , чтобы Room выполнял всю операцию атомарно. Эта аннотация необходима, поскольку функция требует от Room выполнения двух запросов.

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

Составные ключи

Если вы определяете связь с помощью составных ключей, укажите несколько столбцов в parentColumns и entityColumns . Порядок столбцов в parentColumns должен совпадать с порядком столбцов в 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>
)