会议室:如何实现几个一对一的关系?

时间:2019-12-19 21:55:53

标签: android android-room

我可以找到一些示例以及有关如何使用Room实现一对一关系的良好文档,但是找不到关于如何实现几个一对一关系的文档。

这里有一个基于this article的示例。

如果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
)

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

@Entity
data class Owner(@PrimaryKey val ownerId: Long, val name: String)

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

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

和请求:

@Transaction
@Query("SELECT * FROM Owner")
fun getDogsAndOwners(): List<DogAndOwner>

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

我可以创建Home实体:

@Entity
data class Home(@PrimaryKey val homeId: Long, val address: String)

并且我可以使用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
)

现在,问题是,如何创建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
)

但是... Relation注释不可重复,所以我不能。可以通过Room直接检索狗,狗的主人和房屋吗?

预先感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

我相信您可以使用:-

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
)

您可能希望更改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
)

和:-

@Entity
data class Owner(@PrimaryKey val ownerId: Long, val ownername: String)

然后您可以使用(例如):-

@Transaction
@Query("SELECT * FROM Dog")
fun getAllDogsWithOwnerAndHome() : List<DogAndOwnerAndHome>

您将需要会议室库的更高版本之一,例如

kapt 'androidx.room:room-compiler:2.2.3'
implementation 'androidx.room:room-runtime:2.2.3'

演示/测试

使用:-

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

对以上结果进行测试:-

D/DOGDETAILS: Dog name is Woof Owned By Me Lives at Myhouse

答案 1 :(得分:0)

听起来您需要一个复合键来确保1对1的关系:

@Entity(primaryKeys = ["dog","owner"])
data class DogAndOwner(
    val owner: Owner,
    val home: Home,
    val dog: Dog
)