两个实体之间的一对一关系是指这样一种关系:父实体的每个实例恰好对应于子实体的 1 个实例,反之亦然。
例如,假设有一个音乐在线播放应用,用户在该应用中具有一个属于自己的歌曲库。每个用户只有一个库,而且每个库恰好对应于一个用户。因此,User 实体和 Library 实体之间是一对一的关系。
请按照以下步骤在数据库中定义和查询一对一关系:
定义关系
如需定义一对一关系,请先为两个实体分别创建一个类。其中一个实体必须包含一个引用另一个实体主键的变量。
@Entity data class User( @PrimaryKey val userId: Long, val name: String, val age: Int ) @Entity data class Library( @PrimaryKey val libraryId: Long, val userOwnerId: Long )
查询实体
如需查询用户列表和对应的库,您必须先在两个实体之间建立一对一关系。
为了对这种关系进行建模,请创建一个新的数据类,其中每个实例都包含父实体的一个实例和相应的子实体。向子实体添加 @Relation 注释。将 parentColumns 设置为父实体主键列的名称,并将 entityColumns 设置为引用父实体主键的子实体列的名称。
data class UserAndLibrary( @Embedded val user: User, @Relation( parentColumns = ["userId"], entityColumns = ["userOwnerId"] ) val library: Library )
最后,向数据访问对象 (DAO) 类添加一个函数,用于返回将父实体与子实体配对的数据类的所有实例。添加 @Transaction 注释,以确保 Room 以原子方式执行整个操作,因为此函数需要 Room 运行两次查询。
@Transaction @Query("SELECT * FROM User") suspend fun getUsersAndLibraries(): List<UserAndLibrary>
复合键
如果您使用复合键定义关系,请在 parentColumns 和 entityColumns 中指定多个列。parentColumns 中的列顺序必须与 entityColumns 中的列顺序一致。
@Entity(primaryKeys = ["firstName", "lastName"]) data class User( val firstName: String, val lastName: String, val age: Int ) @Entity data class Library( @PrimaryKey val libraryId: Long, val userFirstName: String, val userLastName: String ) data class UserAndLibrary( @Embedded val user: User, @Relation( parentColumns = ["firstName", "lastName"], entityColumns = ["userFirstName", "userLastName"] ) val library: Library )