rolandl
rolandl

Reputation: 1877

Room : how to implement several one-to-one relations?

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

Answers (2)

MikeT
MikeT

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'

Demo/Test

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

Cory Roy
Cory Roy

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

Related Questions