Memilih jenis hubungan antar-objek

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

Blog