En las relaciones de varios a varios entre dos entidades, cada instancia de la entidad principal corresponde a cero o más instancias de la entidad secundaria y viceversa.
En el ejemplo de la app de transmisión de música, imagina las canciones en las playlists definidas por el usuario. Cada playlist puede incluir muchas canciones y cada canción puede ser parte de muchas playlists diferentes. Por lo tanto, existe una relación de varios a varios entre la entidad Playlist
y la entidad Song
.
Sigue estos pasos para definir y consultar relaciones de varios a varios en tu base de datos:
- Define la relación: Establece las entidades y la entidad asociativa (tabla de referencias cruzadas) para representar la relación de varios a varios.
- Consulta las entidades: Determina cómo deseas consultar las entidades relacionadas y crea clases de datos para representar el resultado deseado.
Define la relación
Para definir una relación de varios a varios, primero crea una clase para cada una de las dos entidades. Las relaciones de varios a varios son diferentes de otros tipos de relación porque, por lo general, no hay una referencia a la entidad superior en la entidad secundaria. En su lugar, crea una tercera clase para representar una entidad asociativa (o tabla de referencias cruzadas) entre las dos entidades.
La tabla de referencias cruzadas debe tener columnas para la clave primaria de cada entidad contemplada en la relación de varios a varios que se representa en la tabla. En este ejemplo, cada fila de la tabla de referencias cruzadas corresponde a una vinculación de una instancia Playlist
y una instancia Song
donde la canción a la que se hace referencia se incluye en la playlist a la que se hace referencia.
Kotlin
@Entity
data class Playlist(
@PrimaryKey val playlistId: Long,
val playlistName: String
)
@Entity
data class Song(
@PrimaryKey val songId: Long,
val songName: String,
val artist: String
)
@Entity(primaryKeys = ["playlistId", "songId"])
data class PlaylistSongCrossRef(
val playlistId: Long,
val songId: Long
)
Java
@Entity
public class Playlist {
@PrimaryKey public long playlistId;
public String playlistName;
}
@Entity
public class Song {
@PrimaryKey public long songId;
public String songName;
public String artist;
}
@Entity(primaryKeys = {"playlistId", "songId"})
public class PlaylistSongCrossRef {
public long playlistId;
public long songId;
}
Consulta las entidades
El siguiente paso depende de cómo quieras consultar las entidades relacionadas.
- Si quieres consultar playlists y un listado de las canciones correspondientes por cada playlist, crea una clase de datos nueva con un objeto
Playlist
único y un listado de todos los objetosSong
que incluye la playlist. - Si quieres consultar canciones y un listado de las playlists correspondientes por cada canción, crea una clase de datos nueva con un objeto
Song
único y un listado de los objetosPlaylist
en los que se incluye la canción.
En ambos casos, modela la relación entre las entidades mediante la propiedad associateBy
en la anotación @Relation
de cada una de estas clases para identificar la entidad de la referencia cruzada que proporciona la relación entre las entidades Playlist
y Song
.
Kotlin
data class PlaylistWithSongs(
@Embedded val playlist: Playlist,
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = Junction(PlaylistSongCrossRef::class)
)
val songs: List<Song>
)
data class SongWithPlaylists(
@Embedded val song: Song,
@Relation(
parentColumn = "songId",
entityColumn = "playlistId",
associateBy = Junction(PlaylistSongCrossRef::class)
)
val playlists: List<Playlist>
)
Java
public class PlaylistWithSongs {
@Embedded public Playlist playlist;
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = @Junction(PlaylistSongCrossref.class)
)
public List<Song> songs;
}
public class SongWithPlaylists {
@Embedded public Song song;
@Relation(
parentColumn = "songId",
entityColumn = "playlistId",
associateBy = @Junction(PlaylistSongCrossref.class)
)
public List<Playlist> playlists;
}
Por último, agrega un método a la clase DAO para exponer la función de consulta que necesita la app.
getPlaylistsWithSongs
: Este método busca la base de datos y devuelve todos los objetosPlaylistWithSongs
resultantes.getSongsWithPlaylists
: Este método busca la base de datos y devuelve todos los objetosSongWithPlaylists
resultantes.
Cada uno de los métodos requiere que Room ejecute dos búsquedas, así que agrega la anotación @Transaction
a ambos para asegurarte de que toda la operación se realice automáticamente.
Kotlin
@Transaction
@Query("SELECT * FROM Playlist")
fun getPlaylistsWithSongs(): List<PlaylistWithSongs>
@Transaction
@Query("SELECT * FROM Song")
fun getSongsWithPlaylists(): List<SongWithPlaylists>
Java
@Transaction
@Query("SELECT * FROM Playlist")
public List<PlaylistWithSongs> getPlaylistsWithSongs();
@Transaction
@Query("SELECT * FROM Song")
public List<SongWithPlaylists> getSongsWithPlaylists();