兩個實體之間的「多對多關係」是指父系實體的每個例項分別對應到子實體的零個或更多例項,反之亦然。
在音樂串流應用程式示例中,請考慮使用者定義的播放清單中的歌曲。每個播放清單可包含許多歌曲,而每首歌曲也可能位於不同播放清單中。因此,Playlist
實體和 Song
實體之間是多對多關係。
請按照下列步驟在資料庫中定義及查詢多對多關係:
定義關係
如要定義多對多關係,請先為這兩個實體分別建立類別。由於子實體通常不含父系實體的參照,因此多對多關係與其他關係類型不同。請改為建立第三個類別來代表這兩個實體之間的關聯實體或「交叉參照資料表」。交叉參照資料表必須包含主鍵資料欄,該欄代表資料表內多對多關係中的每個實體。在本例中,交叉參照資料表中的每一個資料列都會對應至一對 Playlist
例項和 Song
例項,其中參照的歌曲會包含在參照的播放清單中。
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;
}
查詢實體
下一個步驟視您想要查詢相關實體的方式而定。
- 如要查詢「播放清單」和每個播放清單的對應「歌曲」清單,請建立新的資料類別,當中包含單一
Playlist
物件以及該播放清單收錄的所有Song
物件清單。 - 如要查詢「歌曲」並列出每首歌曲的對應「播放清單」,請建立新的資料類別,當中包含單一
Song
物件以及收錄該歌曲的所有Playlist
物件清單。
無論是哪一種情況,您都可以在這些類別的 @Relation
註解中使用 associateBy
屬性,建立實體之間的關係模型,以找出建立 Playlist
實體與 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;
}
最後,在 DAO 類別中新增方法,以顯示應用程式所需的查詢函式。
getPlaylistsWithSongs
:這個方法會查詢資料庫,並傳回所有產生的PlaylistWithSongs
物件。getSongsWithPlaylists
:這個方法會查詢資料庫,並傳回所有產生的SongWithPlaylists
物件。
這些方法會分別要求 Room 執行兩項查詢,因此請在這兩種方法中加入 @Transaction
註解,讓整個作業能以不可分割的形式自動執行。
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();