Menentukan dan membuat kueri hubungan many-to-many

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:

  1. Menentukan hubungan: Buat entity dan entity asosiatif (tabel referensi silang) untuk mewakili hubungan many-to-many.
  2. Buat kueri entity: Tentukan cara Anda ingin membuat kueri entity terkait dan membuat 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 secara umum tidak ada referensi ke entity induk dalam entity turunan. Sebagai gantinya, buat class ketiga untuk merepresentasikan entity asosial, 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 dirujuk.

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;
}

Membuat kueri 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 Playlist dan daftar semua objek Song yang disertakan dalam playlist.
  • Jika Anda ingin membuat kueri lagu dan daftar playlist yang sesuai untuk setiap lagu, buat class data baru yang berisi satu objek Song dan daftar semua objek Playlist tempat 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 objek PlaylistWithSongs yang dihasilkan.
  • getSongsWithPlaylists: metode ini membuat kueri database dan menampilkan semua objek SongWithPlaylists yang 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();