定義及查詢一對多關係

兩個實體之間的「一對多關係」是指上層實體的每個例項分別對應到子實體的零個或更多例項,但子實體的每個例項只能確切對應到一個上層實體的例項。

在音樂串流應用程式範例中,假設使用者可以將歌曲整理成多個播放清單。每位使用者可以建立任意數量的播放清單,但是每個播放清單僅由一位使用者建立。因此,User 實體和 Playlist 實體之間是一對多關係。

請按照下列步驟,在資料庫中定義及查詢一對多關係:

  1. 定義關係:為兩個實體建立類別,子項實體會參照父項的主鍵。
  2. 查詢實體:在新資料類別中建立關係模型,並實作函式來擷取相關資料。

定義關係

如要定義一對多關係,請先為每個實體建立類別。與一對一關係相同,子實體必須包含一個參照上層實體主鍵的變數。

@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
)

查詢實體

如要查詢並列出使用者及其對應播放清單,您必須先建立兩個實體之間的一對多關係模型。

如要建立關係模型,請建立新的資料類別。這個類別的每個例項都含有上層實體的例項,以及所有對應子實體例項的清單。將 @Relation 註解新增至代表子實體清單的屬性。將 parentColumns 設為父項實體主鍵資料欄的名稱,並將 entityColumns 設為參照父項實體主鍵的子項實體資料欄名稱。

data class UserWithPlaylists(
    @Embedded val user: User,
    @Relation(
        parentColumns = ["userId"],
        entityColumns = ["userCreatorId"]
    )
    val playlists: List<Playlist>
)

最後,在資料存取物件 (DAO) 類別中新增函式,以傳回將上層實體和子項實體配對的資料類別所有例項。加入 @Transaction 註解,讓 Room 以不可分割的形式執行整個作業。由於函式需要 Room 執行兩項查詢,因此必須使用這項註解。

@Transaction
@Query("SELECT * FROM User")
suspend fun getUsersWithPlaylists(): List<UserWithPlaylists>

複合鍵

如果使用複合鍵定義關係,請在 parentColumnsentityColumns 中指定多個資料欄。parentColumns 中的資料欄順序必須與 entityColumns 中的資料欄順序一致。

@Entity(primaryKeys = ["firstName", "lastName"])
data class User(
    val firstName: String,
    val lastName: String,
    val age: Int
)

@Entity
data class Playlist(
    @PrimaryKey val playlistId: Long,
    val userFirstName: String,
    val userLastName: String,
    val playlistName: String
)

data class UserWithPlaylists(
    @Embedded val user: User,
    @Relation(
        parentColumns = ["firstName", "lastName"],
        entityColumns = ["userFirstName", "userLastName"]
    )
    val playlists: List<Playlist>
)