Terkadang, Anda mungkin perlu membuat kueri kumpulan tiga tabel atau lebih yang semuanya saling berkaitan. Dalam hal ini, Anda menentukan hubungan bertingkat antara tabel.
Misalkan dalam contoh aplikasi streaming musik, Anda ingin membuat kueri semua pengguna, semua playlist untuk setiap pengguna, dan semua lagu di setiap playlist untuk setiap pengguna. Pengguna memiliki hubungan one-to-many dengan playlist, dan playlist memiliki hubungan many-to-many dengan lagu. Contoh kode berikut menunjukkan class yang mewakili entity ini serta tabel referensi silang untuk hubungan many-to-many antara playlist dan lagu:
Kotlin
@Entity
data class User(
@PrimaryKey val userId: Long,
val name: String,
val age: Int
)
@Entity
data class Playlist(
@PrimaryKey val playlistId: Long,
val userCreatorId: 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 User {
@PrimaryKey public long userId;
public String name;
public int age;
}
@Entity
public class Playlist {
@PrimaryKey public long playlistId;
public long userCreatorId;
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;
}
Pertama, buat model hubungan antara dua tabel dalam kumpulan seperti
yang biasa Anda lakukan, menggunakan class data dan anotasi @Relation
.
Contoh berikut menunjukkan class PlaylistWithSongs
yang memodelkan hubungan
many-to-many antara class entity Playlist
dan class entity Song
:
Kotlin
data class PlaylistWithSongs(
@Embedded val playlist: Playlist,
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = Junction(PlaylistSongCrossRef::class)
)
val songs: List<Song>
)
Java
public class PlaylistWithSongs {
@Embedded public Playlist playlist;
@Relation(
parentColumn = "playlistId",
entityColumn = "songId",
associateBy = Junction(PlaylistSongCrossRef.class)
)
public List<Song> songs;
}
Setelah Anda menentukan class data yang merepresentasikan hubungan ini, buat class data
lain yang memodelkan hubungan antara tabel lain dari kumpulan dan
class hubungan pertama, "menyarangkan" hubungan yang ada ke dalam hubungan yang
baru. Contoh berikut menunjukkan class UserWithPlaylistsAndSongs
yang memodelkan
hubungan one-to-many di antara class entity User
dan
class hubungan PlaylistWithSongs
:
Kotlin
data class UserWithPlaylistsAndSongs(
@Embedded val user: User
@Relation(
entity = Playlist::class,
parentColumn = "userId",
entityColumn = "userCreatorId"
)
val playlists: List<PlaylistWithSongs>
)
Java
public class UserWithPlaylistsAndSongs {
@Embedded public User user;
@Relation(
entity = Playlist.class,
parentColumn = "userId",
entityColumn = "userCreatorId"
)
public List<PlaylistWithSongs> playlists;
}
Class UserWithPlaylistsAndSongs
secara tidak langsung memodelkan hubungan
antara ketiga class entity: User
, Playlist
, dan Song
. Hal ini
diilustrasikan dalam gambar 1.
Jika ada tabel lainnya di set Anda, buat class untuk memodelkan hubungan antara setiap tabel yang tersisa dan class hubungan yang memodelkan hubungan antara semua tabel sebelumnya. Hal ini akan membuat rantai hubungan bertingkat di antara semua tabel yang ingin Anda kueri.
Terakhir, tambahkan metode ke class DAO untuk menampilkan fungsi kueri yang
diperlukan aplikasi Anda. Metode ini memerlukan Room untuk menjalankan beberapa kueri, jadi tambahkan
anotasi @Transaction
sehingga seluruh operasi dijalankan
secara atomik:
Kotlin
@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylistsAndSongs(): List<UserWithPlaylistsAndSongs>
Java
@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylistsAndSongs> getUsersWithPlaylistsAndSongs();