Eine m:n-Beziehung zwischen zwei Entitäten ist eine Beziehung, bei der jede Instanz der übergeordneten Entität null oder mehr Instanzen der untergeordneten Entität entspricht und umgekehrt.
Betrachten Sie im Beispiel der Musikstreaming-App die Songs in den nutzerdefinierten Playlists. Jede Playlist kann viele Songs enthalten und jeder Song kann Teil vieler verschiedener Playlists sein. Daher besteht eine m:n-Beziehung zwischen der Entität Playlist und der Entität Song.
So definieren und fragen Sie m:n-Beziehungen in Ihrer Datenbank ab:
- Beziehung definieren: Erstellen Sie die Entitäten und die assoziative Entität (Verweistabelle), um die m:n- Beziehung darzustellen.
- Entitäten abfragen: Legen Sie fest, wie Sie die verknüpften Entitäten abfragen möchten, und erstellen Sie Datenklassen, um die gewünschte Ausgabe darzustellen.
Beziehung definieren
Um eine m:n-Beziehung zu definieren, 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, um eine assoziative
Entität oder Verweistabelle zwischen den beiden Entitäten darzustellen.
Die Verweistabelle muss Spalten für den Primärschlüssel aus jeder Entität in der m:n-Beziehung haben, die in der Tabelle dargestellt wird. In diesem Beispiel entspricht jede Zeile in der Verweistabelle einer Paarung einer Playlist-Instanz und einer Song-Instanz, wobei der referenzierte Song 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 Sie Playlists und eine Liste der entsprechenden Songs für jede Playlist abfragen möchten, erstellen Sie eine neue Datenklasse, die ein einzelnes
Playlist-Objekt und eine Liste allerSong-Objekte enthält, die in der Playlist enthalten sind. - Wenn Sie Songs und eine Liste der entsprechenden Playlists für jeden Song abfragen möchten, erstellen Sie eine neue Datenklasse, die ein einzelnes
Song-Objekt und eine Liste allerPlaylist-Objekte enthält, in denen der Song enthalten ist.
Modellieren Sie in beiden Fällen die Beziehung zwischen den Entitäten mit der
associateBy Property in der @Relation Annotation in jeder dieser
Klassen, um die Verweisentität zu identifizieren, die die Beziehung
zwischen der Playlist Entität und der Song Entität bereitstellt.
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 schließlich eine Methode hinzu, um die Abfragefunktion verfügbar zu machen, die Ihre App benötigt.
getPlaylistsWithSongs: Diese Methode fragt die Datenbank ab und gibt alle resultierendenPlaylistWithSongs-Objekte zurück.getSongsWithPlaylists: Diese Methode fragt die Datenbank ab und gibt alle resultierendenSongWithPlaylists-Objekte zurück.
Für diese Methoden muss Room jeweils zwei Abfragen ausführen. Fügen Sie daher beiden Methoden die
@Transaction Annotation hinzu, damit der gesamte
Vorgang 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();