Связь "один ко многим" между двумя объектами означает, что каждому экземпляру родительского объекта соответствует ноль или более экземпляров дочернего объекта, но каждому экземпляру дочернего объекта может соответствовать только один экземпляр родительского объекта.
Предположим, что в приложении потокового сервиса пользователь может создавать плейлисты. Каждый пользователь может создать любое количество плейлистов, но каждый плейлист может создать только один пользователь. Таким образом, между объектом User и объектом Playlist существует связь "один ко многим".
Чтобы определить и запросить связь "один ко многим" в базе данных, выполните следующие действия:
- Определите связь. Создайте классы для обоих объектов, при этом дочерний объект должен ссылаться на основной ключ родительского.
- Запрашивайте сущности. Создайте новую модель отношений в классе данных и реализуйте функцию для получения связанных данных.
Как определить связь
Чтобы определить связь "один ко многим", сначала создайте класс для каждого объекта. Как и в случае с отношением "один к одному", дочерний объект должен содержать переменную, которая ссылается на первичный ключ родительского объекта.
@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> )