Hubungan many-to-many antara dua entity adalah hubungan saat setiap instance parent entity tidak berkaitan sama sekali atau berkaitan dengan beberapa instance entity turunan, dan hal sebaliknya juga berlaku.
Dalam contoh aplikasi streaming musik, pertimbangkan lagu dalam playlist yang ditentukan pengguna. Setiap playlist dapat berisi banyak lagu, dan setiap lagu dapat menjadi bagian dari banyak playlist yang berbeda. Oleh karena itu, ada hubungan many-to-many
antara entity Playlist dan entity Song.
Ikuti langkah-langkah berikut untuk menentukan dan membuat kueri hubungan many-to-many di database Anda:
- Tentukan hubungan: Tetapkan entity dan entity asosiatif (tabel referensi silang) untuk merepresentasikan hubungan many-to-many.
- Kueri entity: Tentukan cara Anda ingin mengkueri entity terkait dan buat class data untuk merepresentasikan output yang diinginkan.
Menentukan hubungan
Untuk menentukan hubungan many-to-many, buat class untuk kedua entity
Anda terlebih dahulu. Hubungan many-to-many berbeda dengan jenis hubungan lainnya karena umumnya tidak ada referensi ke entity induk dalam entity turunan. Sebagai gantinya, buat class ketiga untuk merepresentasikan entity
asosiatif, atau tabel referensi silang, antara dua entity.
Tabel referensi silang harus memiliki kolom untuk kunci utama dari setiap entity
dalam hubungan many-to-many yang direpresentasikan dalam tabel. Dalam contoh ini, setiap
baris dalam tabel referensi silang berkaitan dengan pasangan instance Playlist
dan instance Song tempat lagu yang dirujuk disertakan dalam
playlist yang direferensikan.
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;
}
Mengkueri entitas
Langkah berikutnya bergantung pada cara Anda ingin membuat kueri entity terkait ini.
- Jika Anda ingin membuat kueri playlist dan daftar lagu terkait untuk
setiap playlist, buat class data baru yang berisi satu objek
Playlistdan daftar semua objekSongyang disertakan dalam playlist. - Jika Anda ingin mengkueri lagu dan daftar playlist yang sesuai untuk setiap
lagu, buat class data baru yang berisi satu objek
Songdan daftar semua objekPlaylisttempat lagu disertakan.
Dalam kedua kasus tersebut, buat model hubungan antara entity dengan menggunakan properti
associateBy dalam anotasi @Relation di setiap class ini untuk mengidentifikasi entity referensi silang yang menyediakan hubungan antara entity Playlist dan entity 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;
}
Terakhir, tambahkan metode ke class DAO untuk menampilkan fungsi kueri yang diperlukan aplikasi Anda.
getPlaylistsWithSongs: metode ini membuat kueri database dan menampilkan semua objekPlaylistWithSongsyang dihasilkan.getSongsWithPlaylists: metode ini membuat kueri database dan menampilkan semua objekSongWithPlaylistsyang dihasilkan.
Masing-masing metode ini memerlukan Room untuk menjalankan dua kueri, jadi tambahkan
anotasi @Transaction ke kedua metode tersebut sehingga seluruh
operasi dilakukan secara atomik.
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();