Définir et interroger des relations plusieurs à plusieurs
Restez organisé à l'aide des collections
Enregistrez et classez les contenus selon vos préférences.
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.
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 objets Song 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 objets Playlist 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.
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 objets PlaylistWithSongs obtenus.
getSongsWithPlaylists : cette méthode interroge la base de données et renvoie tous les objets SongWithPlaylists 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")fungetPlaylistsWithSongs():List<PlaylistWithSongs>@Transaction@Query("SELECT * FROM Song")fungetSongsWithPlaylists():List<SongWithPlaylists>
Java
@Transaction@Query("SELECT * FROM Playlist")publicList<PlaylistWithSongs>getPlaylistsWithSongs();@Transaction@Query("SELECT * FROM Song")publicList<SongWithPlaylists>getSongsWithPlaylists();
Le contenu et les exemples de code de cette page sont soumis aux licences décrites dans la Licence de contenu. Java et OpenJDK sont des marques ou des marques déposées d'Oracle et/ou de ses sociétés affiliées.
Dernière mise à jour le 2025/07/27 (UTC).
[null,null,["Dernière mise à jour le 2025/07/27 (UTC)."],[],[],null,["# Define and query many-to-many relationships\n\nA *many-to-many relationship* between two entities is a relationship where each\ninstance of the parent entity corresponds to zero or more instances of the child\nentity, and the reverse is also true.\n\nIn the music streaming app example, consider the songs in the user-defined\nplaylists. Each playlist can include many songs, and each song can be a part of\nmany different playlists. Therefore, there is a many-to-many relationship\nbetween the `Playlist` entity and the `Song` entity.\n\nFollow these steps to define and query many-to-many relationships in your\ndatabase:\n\n1. **[Define the relationship](#define)**: Establish the entities and the associative entity (cross-reference table) to represent the many-to-many relationship.\n2. **[Query the entities](#query)**: Determine how you want to query the related entities and create data classes to represent the intended output.\n\nDefine the relationship\n-----------------------\n\nTo define a many-to-many relationship, first create a class for each of your two\nentities. Many-to-many relationships are distinct from other relationship types\nbecause there is generally no reference to the parent entity in the child\nentity. Instead, create a third class to represent an [associative\nentity](https://en.wikipedia.org/wiki/Associative_entity), or *cross-reference table* , between the two entities.\nThe cross-reference table must have columns for the primary key from each entity\nin the many-to-many relationship represented in the table. In this example, each\nrow in the cross-reference table corresponds to a pairing of a `Playlist`\ninstance and a `Song` instance where the referenced song is included in the\nreferenced playlist. \n\n### Kotlin\n\n @Entity\n data class Playlist(\n @PrimaryKey val playlistId: Long,\n val playlistName: String\n )\n\n @Entity\n data class Song(\n @PrimaryKey val songId: Long,\n val songName: String,\n val artist: String\n )\n\n @Entity(primaryKeys = [\"playlistId\", \"songId\"])\n data class PlaylistSongCrossRef(\n val playlistId: Long,\n val songId: Long\n )\n\n### Java\n\n @Entity\n public class Playlist {\n @PrimaryKey public long playlistId;\n public String playlistName;\n }\n\n @Entity\n public class Song {\n @PrimaryKey public long songId;\n public String songName;\n public String artist;\n }\n\n @Entity(primaryKeys = {\"playlistId\", \"songId\"})\n public class PlaylistSongCrossRef {\n public long playlistId;\n public long songId;\n }\n\nQuery the entities\n------------------\n\nThe next step depends on how you want to query these related entities.\n\n- If you want to query *playlists* and a list of the corresponding *songs* for each playlist, create a new data class that contains a single `Playlist` object and a list of all of the `Song` objects that the playlist includes.\n- If you want to query *songs* and a list of the corresponding *playlists* for each, create a new data class that contains a single `Song` object and a list of all of the `Playlist` objects in which the song is included.\n\nIn either case, model the relationship between the entities by using the\n[`associateBy`](/reference/kotlin/androidx/room/Relation#associateBy()) property in the [`@Relation`](/reference/kotlin/androidx/room/Relation) annotation in each of these\nclasses to identify the cross-reference entity providing the relationship\nbetween the `Playlist` entity and the `Song` entity. \n\n### Kotlin\n\n data class PlaylistWithSongs(\n @Embedded val playlist: Playlist,\n @Relation(\n parentColumn = \"playlistId\",\n entityColumn = \"songId\",\n associateBy = Junction(PlaylistSongCrossRef::class)\n )\n val songs: List\u003cSong\u003e\n )\n\n data class SongWithPlaylists(\n @Embedded val song: Song,\n @Relation(\n parentColumn = \"songId\",\n entityColumn = \"playlistId\",\n associateBy = Junction(PlaylistSongCrossRef::class)\n )\n val playlists: List\u003cPlaylist\u003e\n )\n\n### Java\n\n public class PlaylistWithSongs {\n @Embedded public Playlist playlist;\n @Relation(\n parentColumn = \"playlistId\",\n entityColumn = \"songId\",\n associateBy = @Junction(PlaylistSongCrossref.class)\n )\n public List\u003cSong\u003e songs;\n }\n\n public class SongWithPlaylists {\n @Embedded public Song song;\n @Relation(\n parentColumn = \"songId\",\n entityColumn = \"playlistId\",\n associateBy = @Junction(PlaylistSongCrossref.class)\n )\n public List\u003cPlaylist\u003e playlists;\n }\n\nFinally, add a method to the DAO class to expose the query function your\napp needs.\n\n- `getPlaylistsWithSongs`: this method queries the database and returns all the resulting `PlaylistWithSongs` objects.\n- `getSongsWithPlaylists`: this method queries the database and returns all the resulting `SongWithPlaylists` objects.\n\nThese methods each require Room to run two queries, so add the\n[`@Transaction`](/reference/kotlin/androidx/room/Transaction) annotation to both methods so that the whole\noperation is performed atomically. \n\n### Kotlin\n\n @Transaction\n @Query(\"SELECT * FROM Playlist\")\n fun getPlaylistsWithSongs(): List\u003cPlaylistWithSongs\u003e\n\n @Transaction\n @Query(\"SELECT * FROM Song\")\n fun getSongsWithPlaylists(): List\u003cSongWithPlaylists\u003e\n\n### Java\n\n @Transaction\n @Query(\"SELECT * FROM Playlist\")\n public List\u003cPlaylistWithSongs\u003e getPlaylistsWithSongs();\n\n @Transaction\n @Query(\"SELECT * FROM Song\")\n public List\u003cSongWithPlaylists\u003e getSongsWithPlaylists();\n\n| **Note:** If the `@Relation` annotation does not meet your specific use case, you might need to use the `JOIN` keyword in your SQL queries to manually define the appropriate relationships. To learn more about querying multiple tables manually, read [Accessing data using Room\n| DAOs](/training/data-storage/room/accessing-data#query-multiple-tables)."]]