Karena SQLite merupakan database relasional, Anda dapat menentukan hubungan antara entity. Namun, meskipun sebagian besar library pemetaan terkait objek memungkinkan objek entity saling mereferensikan satu sama lain, Room secara eksplisit melarang hal ini. Untuk mempelajari alasan teknis di balik keputusan ini, lihat Memahami alasan Room tidak mengizinkan referensi objek.
Jenis hubungan
Room mendukung jenis hubungan berikut:
- One-to-one: Mewakili hubungan saat satu entity terkait dengan satu entity lain.
- One-to-many: Merepresentasikan hubungan saat satu entity dapat terkait dengan beberapa entity dari jenis lain.
- Many-to-many: Merepresentasikan hubungan saat beberapa entity dari satu jenis dapat dikaitkan dengan beberapa entity dari jenis lain. Hal ini biasanya memerlukan tabel gabungan.
- Hubungan Bertingkat (menggunakan objek tersemat): Merepresentasikan
hubungan saat entitas berisi entitas lain sebagai kolom, dan entitas
bertingkat ini selanjutnya dapat berisi entitas lain. Ini menggunakan anotasi
@Embedded
.
Memilih antara dua pendekatan
Di Room, ada dua cara untuk menentukan dan membuat kueri hubungan antar-entity. Anda dapat menggunakan:
- Class data perantara dengan objek tersemat, atau
- Metode kueri relasional dengan jenis nilai yang ditampilkan multimap.
Jika Anda tidak memiliki alasan khusus untuk menggunakan class data perantara, sebaiknya gunakan pendekatan jenis nilai yang ditampilkan multimap. Untuk mempelajari pendekatan ini lebih lanjut, lihat Menampilkan multimap.
Pendekatan class data perantara memungkinkan Anda untuk tidak menulis kueri SQL yang kompleks, tetapi juga dapat mengakibatkan peningkatan kerumitan kode karena memerlukan class data tambahan. Singkatnya, pendekatan jenis nilai yang ditampilkan multimap memerlukan kueri SQL Anda untuk melakukan lebih banyak pekerjaan, dan pendekatan class data perantara memerlukan kode Anda untuk melakukan lebih banyak pekerjaan.
Menggunakan pendekatan class data menengah
Dalam pendekatan class data perantara, Anda menentukan class data yang memodelkan hubungan antara entity Room. Class data ini menyimpan penyambungan antara instance satu entity dan instance entity lain sebagai objek tersemat. Metode kueri Anda kemudian dapat menampilkan instance class data ini untuk digunakan dalam aplikasi.
Misalnya, Anda dapat menentukan class data UserBook
untuk mewakili pengguna library
dengan buku tertentu yang diperiksa, dan menentukan metode kueri untuk mengambil daftar
instance UserBook
dari database:
Kotlin
@Dao
interface UserBookDao {
@Query(
"SELECT user.name AS userName, book.name AS bookName " +
"FROM user, book " +
"WHERE user.id = book.user_id"
)
fun loadUserAndBookNames(): LiveData<List<UserBook>>
}
data class UserBook(val userName: String?, val bookName: String?)
Java
@Dao
public interface UserBookDao {
@Query("SELECT user.name AS userName, book.name AS bookName " +
"FROM user, book " +
"WHERE user.id = book.user_id")
public LiveData<List<UserBook>> loadUserAndBookNames();
}
public class UserBook {
public String userName;
public String bookName;
}
Menggunakan pendekatan jenis nilai yang ditampilkan multimap
Dalam pendekatan jenis nilai yang ditampilkan multimap, Anda tidak perlu menentukan class data tambahan apa pun. Sebagai gantinya, Anda harus menentukan jenis nilai yang ditampilkan multimap untuk metode Anda berdasarkan struktur peta yang diinginkan, dan tentukan hubungan antara entity Anda secara langsung dalam kueri SQL.
Misalnya, metode kueri berikut menampilkan pemetaan instance User
dan Book
untuk mewakili pengguna library dengan buku tertentu yang diperiksa:
Kotlin
@Query(
"SELECT * FROM user" +
"JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<User, List<Book>>
Java
@Query(
"SELECT * FROM user" +
"JOIN book ON user.id = book.user_id"
)
public Map<User, List<Book>> loadUserAndBookNames();
Membuat objek yang disematkan
Terkadang, Anda perlu menyatakan entity atau objek data sebagai satu kesatuan yang kohesif dalam
logika database, meskipun objek berisi beberapa kolom. Dalam situasi
ini, Anda dapat menggunakan anotasi @Embedded
untuk merepresentasikan objek
yang ingin didekomposisi ke subkolomnya dalam tabel. Anda kemudian dapat
meminta kolom tersemat tersebut seperti saat meminta kolom individual lainnya.
Misalnya, class User
dapat menyertakan kolom dari jenis Address
yang
merepresentasikan susunan kolom bernama street
, city
, state
, dan
postCode
. Untuk menyimpan kolom tersusun secara terpisah dalam tabel, sertakan
kolom Address
. Ini akan muncul di class User
yang dianotasi dengan
@Embedded
. Cuplikan kode berikut menunjukkan hal ini:
Kotlin
data class Address(
val street: String?,
val state: String?,
val city: String?,
@ColumnInfo(name = "post_code") val postCode: Int
)
@Entity
data class User(
@PrimaryKey val id: Int,
val firstName: String?,
@Embedded val address: Address?
)
Java
public class Address {
public String street;
public String state;
public String city;
@ColumnInfo(name = "post_code") public int postCode;
}
@Entity
public class User {
@PrimaryKey public int id;
public String firstName;
@Embedded public Address address;
}
Tabel yang merepresentasikan objek User
kemudian akan berisi kolom dengan nama
berikut: id
, firstName
, street
, state
, city
, dan post_code
.
Jika suatu entity memiliki beberapa kolom tersemat yang jenisnya sama, Anda dapat mengatur setiap
kolom agar tetap unik dengan menetapkan properti prefix
. Room kemudian menambahkan
nilai yang diberikan ke awal setiap nama kolom dalam objek tersemat.
Referensi lainnya
Untuk mempelajari lebih lanjut cara menentukan hubungan antara entity di Room, lihat referensi tambahan berikut.
Video
- Yang Baru di Room (Android Dev Summit '19)