Es posible que, en ocasiones, debas buscar un conjunto de tres o más tablas relacionadas entre sí. En ese caso, definirías relaciones anidadas entre las tablas.
Supongamos que, en el ejemplo de la app de transmisión de música, quieres consultar todos los usuarios, todas las playlists de cada uno de ellos y todas las canciones de cada playlist de cada usuario. Los usuarios tienen una relación uno a varios con las listas de reproducción, y estas tienen una relación varios a varios con las canciones. En el siguiente ejemplo de código, se muestran las clases que representan las entidades, así como la tabla de referencias cruzadas de la relación de varios a varios entre las playlists y las canciones:
@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 )
Primero, modela la relación entre dos de las tablas del conjunto como lo harías
normalmente, con una clase de datos y la @Relation anotación. En el
siguiente ejemplo, se muestra una clase PlaylistWithSongs que modela una relación de varios a varios
entre la clase de entidad Playlist y la clase de entidad Song:
data class PlaylistWithSongs( @Embedded val playlist: Playlist, @Relation( parentColumns = ["playlistId"], entityColumns = ["songId"], associateBy = Junction(PlaylistSongCrossRef::class) ) val songs: List<Song> )
Después de definir una clase de datos que represente esa relación, crea otra clase de datos que modele la relación entre otra tabla del conjunto y la primera clase de relación, y "anida" la relación existente dentro de la nueva. En el siguiente ejemplo, se muestra una clase UserWithPlaylistsAndSongs que modela
una relación de uno a varios entre la clase de entidad User y la
PlaylistWithSongs clase de relación:
data class UserWithPlaylistsAndSongs( @Embedded val user: User, @Relation( entity = Playlist::class, parentColumns = ["userId"], entityColumns = ["userCreatorId"] ) val playlists: List<PlaylistWithSongs> )
La clase UserWithPlaylistsAndSongs modela indirectamente las relaciones
entre las tres clases de entidad: User, Playlist, y Song. Esto se ilustra en la figura 1.
Si el conjunto tiene más tablas, crea una clase para modelar la relación entre cada tabla restante y la clase de relación anterior. Este proceso crea una cadena de relaciones anidadas entre todas las tablas que quieres consultar.
Por último, agrega una función a la clase de objeto de acceso a datos (DAO) para exponer la función de consulta que necesita la app. Esta función requiere que Room ejecute
varias búsquedas, así que agrega la @Transaction anotación para asegurarte de que toda la
operación se realice automáticamente:
@Transaction @Query("SELECT * FROM User") suspend fun getUsersWithPlaylistsAndSongs(): List<UserWithPlaylistsAndSongs>