Иногда может потребоваться запрос к набору из трех или более таблиц, которые связаны между собой. В этом случае вы определяете вложенные связи между таблицами.
Предположим, в примере с приложением для потоковой передачи музыки вам нужно запросить всех пользователей, все плейлисты для каждого пользователя и все песни в каждом плейлисте для каждого пользователя. Пользователи имеют отношение «один ко многим» с плейлистами, а плейлисты имеют отношение «многие ко многим» с песнями. В следующем примере кода показаны классы, представляющие эти сущности, а также таблица перекрестных ссылок для отношения «многие ко многим» между плейлистами и песнями:
@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 ) @Entity data class Song( @PrimaryKey val songId: Long, val songName: String, val artist: String ) @Entity(primaryKeys = ["playlistId", "songId"], indices = [Index("playlistId", "songId")]) data class PlaylistSongCrossRef( val playlistId: Long, val songId: Long )
Сначала смоделируйте связь между двумя таблицами в вашем наборе, как обычно, используя класс данных и аннотацию @Relation . В следующем примере показан класс PlaylistWithSongs , который моделирует связь «многие ко многим» между классом сущности Playlist и классом сущности Song :
data class PlaylistWithSongs( @Embedded val playlist: Playlist, @Relation( parentColumns = ["playlistId"], entityColumns = ["songId"], associateBy = Junction(PlaylistSongCrossRef::class) ) val songs: List<Song> )
После определения класса данных, представляющего эту связь, создайте еще один класс данных, моделирующий связь между другой таблицей из вашего набора и первым классом связи, «вкладывая» существующую связь в новую. В следующем примере показан класс UserWithPlaylistsAndSongs , моделирующий связь «один ко многим» между классом сущности User и классом связи PlaylistWithSongs :
data class UserWithPlaylistsAndSongs( @Embedded val user: User, @Relation( entity = Playlist::class, parentColumns = ["userId"], entityColumns = ["userCreatorId"] ) val playlists: List<PlaylistWithSongs> )
Класс UserWithPlaylistsAndSongs косвенно моделирует взаимосвязи между всеми тремя классами сущностей: User , Playlist и Song . Это показано на рисунке 1.

Если ваш набор данных содержит несколько таблиц, создайте класс для моделирования связи между каждой оставшейся таблицей и предыдущим классом связей. Этот процесс создаст цепочку вложенных связей между всеми таблицами, к которым вы хотите обращаться с запросами.
Наконец, добавьте функцию в класс объекта доступа к данным (DAO), чтобы предоставить доступ к функции запроса, необходимой вашему приложению. Для выполнения нескольких запросов этой функции требуется Room, поэтому добавьте аннотацию @Transaction , чтобы вся операция выполнялась атомарно:
@Transaction @Query("SELECT * FROM User") suspend fun getUsersWithPlaylistsAndSongs(): List<UserWithPlaylistsAndSongs>