兩個實體之間的「一對多關係」是指上層實體的每個例項分別對應到子實體的零個或更多例項,但子實體的每個例項只能確切對應到一個上層實體的例項。
在音樂串流應用程式範例中,假設使用者可以將歌曲整理成多個播放清單。每位使用者可以建立任意數量的播放清單,但是每個播放清單僅由一位使用者建立。因此,User 實體和 Playlist 實體之間是一對多關係。
請按照下列步驟,在資料庫中定義及查詢一對多關係:
定義關係
如要定義一對多關係,請先為每個實體建立類別。與一對一關係相同,子實體必須包含一個參照上層實體主鍵的變數。
@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>
複合鍵
如果使用複合鍵定義關係,請在 parentColumns 和 entityColumns 中指定多個資料欄。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> )