Eine Mehrfachbeziehung zwischen zwei Entitäten ist eine Beziehung, bei der jeder Instanz der übergeordneten Entität null oder mehr Instanzen der untergeordneten Entität entsprechen und umgekehrt.
Denken Sie im Beispiel für die Musik-Streaming-App an die Titel in den benutzerdefinierten Playlists. Jede Playlist kann viele Titel enthalten und jeder Titel kann Teil vieler verschiedener Playlists sein. Daher besteht zwischen der Entität Playlist
und der Entität Song
eine m:n-Beziehung.
So definieren und abfragen Sie Beziehungen vom Typ „Mehrfach zu Mehrfach“ in Ihrer Datenbank:
- Beziehung definieren: Legen Sie die Entitäten und die assoziative Entität (Verweistabelle) fest, um die m:n-Beziehung darzustellen.
- Entitäten abfragen: Legen Sie fest, wie Sie die zugehörigen Entitäten abfragen möchten, und erstellen Sie Datenklassen, um die gewünschte Ausgabe darzustellen.
Beziehung definieren
Wenn Sie eine n:n-Beziehung definieren möchten, erstellen Sie zuerst eine Klasse für jede Ihrer beiden Entitäten. m:n-Beziehungen unterscheiden sich von anderen Beziehungstypen, da es in der untergeordneten Entität in der Regel keinen Verweis auf die übergeordnete Entität gibt. Erstellen Sie stattdessen eine dritte Klasse, die eine assoziative Entität oder eine Verweistabelle zwischen den beiden Entitäten darstellt.
Die Referenztabelle muss Spalten für den Primärschlüssel jeder Entität in der in der Tabelle dargestellten Beziehung vom Typ „Mehrfach zueinander“ enthalten. In diesem Beispiel entspricht jede Zeile in der Verweistabelle einer Verknüpfung zwischen einer Playlist
-Instanz und einer Song
-Instanz, bei der der referenzierte Titel in der referenzierten Playlist enthalten ist.
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;
}
Entitäten abfragen
Der nächste Schritt hängt davon ab, wie Sie diese verknüpften Entitäten abfragen möchten.
- Wenn du Playlists und eine Liste der entsprechenden Songs für jede Playlist abfragen möchtest, erstelle eine neue Datenklasse, die ein einzelnes
Playlist
-Objekt und eine Liste allerSong
-Objekte enthält, die in der Playlist enthalten sind. - Wenn du Songs und eine Liste der entsprechenden Playlists abfragen möchtest, erstelle eine neue Datenklasse mit einem einzelnen
Song
-Objekt und einer Liste allerPlaylist
-Objekte, in denen der Song enthalten ist.
In beiden Fällen modellieren Sie die Beziehung zwischen den Entitäten mithilfe der Property associateBy
in der Annotation @Relation
in jeder dieser Klassen, um die Verweis-Entität zu identifizieren, die die Beziehung zwischen der Playlist
-Entität und der Song
-Entität herstellt.
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;
}
Fügen Sie der DAO-Klasse abschließend eine Methode hinzu, um die Abfragefunktion für Ihre App freizugeben.
getPlaylistsWithSongs
: Mit dieser Methode wird die Datenbank abgefragt und alle resultierendenPlaylistWithSongs
-Objekte zurückgegeben.getSongsWithPlaylists
: Mit dieser Methode wird die Datenbank abgefragt und alle resultierendenSongWithPlaylists
-Objekte zurückgegeben.
Für diese Methoden muss Room jeweils zwei Abfragen ausführen. Fügen Sie daher beiden Methoden die Annotation @Transaction
hinzu, damit die gesamte Operation atomar ausgeführt wird.
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();