Room:如何实现几个一对一的关系?

rol*_*ndl 0 android android-room

我可以找到有关如何使用 Room 实现一对一关系的几个示例和一个很好的文档,但我找不到任何有关如何实现多个一对一关系的文档。

这是基于本文的示例。

如果 1 只狗有 1 个主人,我可以创建一个Dog实体:

@Entity
data class Dog(
    @PrimaryKey val dogId: Long,
    val dogOwnerId: Long,
    val name: String,
    val cuteness: Int,
    val barkVolume: Int,
    val breed: String
)
Run Code Online (Sandbox Code Playgroud)

然后我可以创建一个Owner实体:

@Entity
data class Owner(@PrimaryKey val ownerId: Long, val name: String)
Run Code Online (Sandbox Code Playgroud)

现在,我可以创建一个DogAndOwner数据类,以便使用 Room 检索狗及其主人:

data class DogAndOwner(
    @Embedded val owner: Owner,
    @Relation(
         parentColumn = "ownerId",
         entityColumn = "dogOwnerId"
    )
    val dog: Dog
)
Run Code Online (Sandbox Code Playgroud)

和请求:

@Transaction
@Query("SELECT * FROM Owner")
fun getDogsAndOwners(): List<DogAndOwner>
Run Code Online (Sandbox Code Playgroud)

现在,我想为我的狗添加另一个一对一的关系,例如家。

我可以创建Home实体:

@Entity
data class Home(@PrimaryKey val homeId: Long, val address: String)
Run Code Online (Sandbox Code Playgroud)

我可以Dog使用属性更新我的实体dogHome

@Entity
data class Dog(
    @PrimaryKey val dogId: Long,
    val dogOwnerId: Long,
    val dogHomeId: Long,
    val name: String,
    val cuteness: Int,
    val barkVolume: Int,
    val breed: String
)
Run Code Online (Sandbox Code Playgroud)

现在的问题是,如何创建DogAndOwnerAndHome数据类?我想写这样的东西:

data class DogAndOwner(
    @Embedded val owner: Owner,
    @Embedded val home: Home,
    @Relation(
         parentColumn = "ownerId",
         entityColumn = "dogOwnerId"
    )
    @Relation(
         parentColumn = "homeId",
         entityColumn = "dogHomeId"
    )
    val dog: Dog
)
Run Code Online (Sandbox Code Playgroud)

但是...Relation注释不可重复,所以我不能。可以使用 Room 直接检索狗、它的主人和它的家吗?

预先感谢您的帮助。

Mik*_*keT 5

我相信你可以使用:-

data class DogAndOwnerAndHome (
    @Embedded
    val dog: Dog,
    @Relation(entity = Owner::class,parentColumn = "dogOwnerId", entityColumn = "ownerId" )
    val owner: Owner,
    @Relation(entity = Home::class,parentColumn = "dogHomeId", entityColumn = "homeId" )
    val home: Home
)
Run Code Online (Sandbox Code Playgroud)

您可能希望更改 Dog 和 Owner 实体以确保列名称是唯一的,例如:-

@Entity
data class Dog(
    @PrimaryKey val dogId: Long,
    val dogOwnerId: Long,
    val dogHomeId: Long,
    val dogname: String,
    val dogcuteness: Int,
    val dogbarkVolume: Int,
    val dogbreed: String
)
Run Code Online (Sandbox Code Playgroud)

和 :-

@Entity
data class Owner(@PrimaryKey val ownerId: Long, val ownername: String)
Run Code Online (Sandbox Code Playgroud)

然后您可以使用(作为示例):-

@Transaction
@Query("SELECT * FROM Dog")
fun getAllDogsWithOwnerAndHome() : List<DogAndOwnerAndHome>
Run Code Online (Sandbox Code Playgroud)

您将需要房间库的更高版本之一,例如

kapt 'androidx.room:room-compiler:2.2.3'
implementation 'androidx.room:room-runtime:2.2.3'
Run Code Online (Sandbox Code Playgroud)

演示/测试

使用 :-

    val database = Room.databaseBuilder(this,AppDatabase::class.java,"petdb")
        .allowMainThreadQueries()
        .build()
    val homeid = database.allDao().insertHome(Home(0,"Myhouse"))
    val ownerid = database.allDao().insertOwner(Owner(0,"Me"))
    val dogid = database.allDao().insertDog(Dog(0,ownerid,homeid,"Woof",1,0,"terrier"))


    val alldogswithownerandwithhome = database.allDao().getAllDogsWithOwnerAndHome()
    for (dwoh: DogAndOwnerAndHome in alldogswithownerandwithhome) {
        Log.d("DOGDETAILS","Dog name is " + dwoh.dog.dogname + " Owned By " + dwoh.owner.ownername + " Lives at " + dwoh.home.address)
    }
Run Code Online (Sandbox Code Playgroud)

测试上述结果:-

D/DOGDETAILS: Dog name is Woof Owned By Me Lives at Myhouse
Run Code Online (Sandbox Code Playgroud)