@Entity, @Embedded and Composite Primary Keys with Room DB

Android implementation in Kotlin

Photo by Caspar Rubin on Unsplash

@Entity creates a table for each class it’s annotated with, and so the class itself is essentially a data class that doesn’t contain logic.

Data classes hold data.

And @Entity makes a table out of the data class.

The @Entity annotation indicates that the data class is to be mapped to a database.

But the address variables relate directly to Address and not to Person.

Multiple variables relate to Address which in turn relates to Person. Therefore, it does sound more competent to use an object for storing the address.

Then, we would need to access the variables, for example, city, as:

person.address.city

So what if all these variables needed to be directly accessed from Person as person.city?

@Embedded makes this happen.

In a data class, this annotation indicates that the instance of the class being embedded is stored as an intrinsic part of the class where the annotation is being used.

@Embedded can be used to ‘snapshot’ the state of a related class inside the parent class.

Meaning, the structuring of the data isn’t actually changed. The fields from the embedded class are merged with the parent class. These fields can be used as if they were declared in the parent class as required.

person.city

When multiple fields are closely related, but your data is not structured to create an object enclosing those multiple fields, @Embedded may be used to access the data as required, making the code more readable and maintainable.

Composite Primary Key

In JPA (Java Persistence API), we can add multiple Primary Keys by creating an @Embeddable class. Using it in the @Entity class as @EmbeddedId would be sufficient for a composite Primary Key.

In Kotlin, while @Embedded is certainly a point in favour of Room, there are certain points to keep in mind with respect to Primary Keys as well.

An @Embedded field cannot contain Primary Key.

If sub fields of an embedded field has PrimaryKey annotation, they will not be considered as primary keys in the owner Entity.

If multiple primary keys are to be defined, then a list of Primary Key column names may be defined as:

String[] primaryKeys ()

However, in this case, the Primary Key may not be set as auto-generated.

If a Primary Key needs to be set as auto-generated, a single Primary Key may be used and defined as auto-generated in the @Entity data class.

@PrimaryKey(autoGenerate = true)    
val id: Long

There is one more option.

If PrimaryKey annotation is used on an Embedded field, all columns inherited from that embedded field becomes the composite primary key (including its grand children fields).

More annotations for Room database are here.

Android/RN dev | WWCode Tokyo Lead | Writer | Hypocrite with an appreciation of the beautiful horror of femininity | she/her.

Android/RN dev | WWCode Tokyo Lead | Writer | Hypocrite with an appreciation of the beautiful horror of femininity | she/her.