Une relation de type plusieurs à plusieurs entre deux entités est une relation dans laquelle chaque instance de l'entité parente correspond à zéro instance ou plus de l'entité enfant, et inversement.
Reprenons à nouveau l'exemple de l'application de streaming musical et penchons-nous sur les titres des playlists définies par l'utilisateur. Chaque playlist peut inclure de nombreux titres, et chacun d'eux peut faire partie de différentes playlists. Par conséquent, il existe une relation de plusieurs à plusieurs entre l'entité Playlist
et l'entité Song
.
Pour définir et interroger des relations de type plusieurs à plusieurs dans votre base de données, procédez comme suit:
- Définir la relation: définissez les entités et l'entité associative (tableau de correspondance) pour représenter la relation de plusieurs à plusieurs.
- Interroger les entités: déterminez comment vous souhaitez interroger les entités associées et créez des classes de données pour représenter la sortie souhaitée.
Définir la relation
Pour définir une relation de plusieurs à plusieurs, créez d'abord une classe pour chacune de vos deux entités. Les relations de type plusieurs à plusieurs se distinguent des autres types de relations, car il n'existe en général aucune référence à l'entité parente dans l'entité enfant. Créez plutôt une troisième classe pour représenter une entité associative (ou tableau de concordance) entre les deux entités.
Le tableau de concordance doit comporter des colonnes pour la clé primaire de chaque entité dans la relation de type plusieurs à plusieurs représentée dans le tableau. Dans cet exemple, chaque ligne du tableau de concordance correspond à l'association d'une instance Playlist
et d'une instance Song
, où le titre référencé est inclus dans la playlist référencée.
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;
}
Interroger les entités
L'étape suivante dépend de la façon dont vous souhaitez interroger ces entités associées.
- Si vous souhaitez interroger des playlists et une liste des chansons correspondant à chaque playlist, créez une classe de données contenant un seul élément
Playlist
et une liste de tous les objetsSong
inclus dans la playlist. - Si vous souhaitez interroger des chansons et une liste des playlists correspondant à chaque chanson, créez une classe de données contenant un seul objet
Song
et une liste de tous les objetsPlaylist
dans lesquels le titre est inclus.
Dans les deux cas, représentez la relation entre les entités à l'aide de la propriété associateBy
de l'annotation @Relation
dans chacune de ces classes pour identifier l'entité de concordance déterminant la relation entre l'entité Playlist
et l'entité 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;
}
Enfin, ajoutez une méthode à la classe DAO pour afficher la fonction de requête nécessaire à votre application.
getPlaylistsWithSongs
: cette méthode interroge la base de données et renvoie tous les objetsPlaylistWithSongs
obtenus.getSongsWithPlaylists
: cette méthode interroge la base de données et renvoie tous les objetsSongWithPlaylists
obtenus.
Ces méthodes nécessitent que Room exécute deux requêtes. Vous devez donc ajouter l'annotation @Transaction
aux deux méthodes pour vous assurer que toute l'opération est effectuée de manière atomique.
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();