Reputation: 1877
I can find several examples and a good documentation on how to implement a one-to-one relation using Room, but I cannot find any documentation on how to implement several one-to-one relations.
Here an example based on this article.
If 1 dog has 1 owner, I can create a Dog
entity:
@Entity
data class Dog(
@PrimaryKey val dogId: Long,
val dogOwnerId: Long,
val name: String,
val cuteness: Int,
val barkVolume: Int,
val breed: String
)
Then I can create a Owner
entity:
@Entity
data class Owner(@PrimaryKey val ownerId: Long, val name: String)
Now, I can create a DogAndOwner
data class in order to retrieve a dog and its owner with Room:
data class DogAndOwner(
@Embedded val owner: Owner,
@Relation(
parentColumn = "ownerId",
entityColumn = "dogOwnerId"
)
val dog: Dog
)
and the request:
@Transaction
@Query("SELECT * FROM Owner")
fun getDogsAndOwners(): List<DogAndOwner>
Now, I would like to add another one-to-one relation to my dog, for example a home.
I can create the Home
entity:
@Entity
data class Home(@PrimaryKey val homeId: Long, val address: String)
and I can update my Dog
entity with the dogHome
attribute:
@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
)
Now, the question is, how to create a DogAndOwnerAndHome
data class? I would like to write something like that:
data class DogAndOwner(
@Embedded val owner: Owner,
@Embedded val home: Home,
@Relation(
parentColumn = "ownerId",
entityColumn = "dogOwnerId"
)
@Relation(
parentColumn = "homeId",
entityColumn = "dogHomeId"
)
val dog: Dog
)
but... the Relation
annotation is not repeatable so I cannot. It is possible to retrieve directly a dog, its owner and its home with Room ?
Thank you in advance for your help.
Upvotes: 0
Views: 1530
Reputation: 56938
I believe that you can use :-
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
)
You may wish to change the Dog and Owner entities to ensure that column names are unique e.g. :-
@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
)
and :-
@Entity
data class Owner(@PrimaryKey val ownerId: Long, val ownername: String)
You can then use (as an example) :-
@Transaction
@Query("SELECT * FROM Dog")
fun getAllDogsWithOwnerAndHome() : List<DogAndOwnerAndHome>
You will need one of the later versions of the room libraries e.g.
kapt 'androidx.room:room-compiler:2.2.3'
implementation 'androidx.room:room-runtime:2.2.3'
Using :-
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)
}
Testing the above results in :-
D/DOGDETAILS: Dog name is Woof Owned By Me Lives at Myhouse
Upvotes: 5
Reputation: 5609
It sound like you need a composite key to ensure 1 to 1 relationships:
@Entity(primaryKeys = ["dog","owner"])
data class DogAndOwner(
val owner: Owner,
val home: Home,
val dog: Dog
)
Upvotes: 0