Entity Relationship in Room

Deepanshu
MindOrks
Published in
5 min readMay 23, 2020

Note: This article is part of the advanced Room series which covers all the details about the Room persistence library. You can read all the articles here:

Entity Relationships in Room

This article covers how we can define relationship between entities in Room persistence library.

Since SQLite is a relational database, entities can have relationships between them. In Room, entities cannot directly reference other entities because it might cause loading unnecessary data every time.

Still sometimes, you would want to reference other entities from your entity. You can acheive this in multiple ways.

Embedded Objects

You can use the @Embedded annotation to represent an object that you'd like to decompose into its subfields within a table(entity). You can then query the embedded fields just as you would for other individual columns.

Embedded fields can also include other embedded fields.

The table representing a User object then contains columns with the following names: id, firstName, street, state, city, and postCode.

If an entity has multiple embedded fields of the same type, you can keep each column unique by setting the prefix property. Room then adds the provided value to the beginning of each column name in the embedded object.

In the above example, fields of an object are decomposed into an entity. In case you want to represent relationship between multiple entities, you cannot use the @Embedded annotation.

You can use either @Relation annotation or foreignkeys parameter of @Entity annotation for defining relationship between two entities.
Both of them are different from each other in such a way that @Relation annotation can only be applied on a non-entity class whereas ForeignKey is used on an entity class. Also, ForeignKey affects the schema of an entity that requires that the child column(s) exist in the parent column(s). @Relation is used to join the tables without affecting the schema of tables.

You can define relationship between entities in 3 ways:

  • One-to-one relationship
  • One-to-many relationship or Many-to-one relationship
  • Many-to-many relationship

One-to-one relationships

A one-to-one relationship between two entities is a relationship where each instance of the parent entity corresponds to exactly one instance of the child entity, and vice-versa.

For example, consider a music streaming app where the user has a library of songs that they own. Each user has only one library, and each library corresponds to exactly one user.

In the above example, User and Library are the entities which have one-to-one relationship. One of the entities must include a variable that is a reference to the primary key of the other entity(userOwnerId in Library entity).

In order to query the list of users and corresponding libraries, we must first model the one-to-one relationship between the two entities, which is done using UserAndLibrary class. The UserAndLibrary class contains an instance of the parent entity(User) and the corresponding instance of the child entity(Library). Then, add the @Relation annotation to the instance of the child entity, with parentColumn set to the name of the primary key column of the parent entity and entityColumn set to the name of the column of the child entity that references the parent entity's primary key.

Now we can query our database in the following way:

This method requires Room to run two queries, so add the @Transaction annotation to this method to ensure that the whole operation is performed atomically.

One-to-many relationships

A one-to-many relationship between two entities is a relationship where each instance of the parent entity corresponds to zero or more instances of the child entity, but each instance of the child entity can only correspond to exactly one instance of the parent entity.

In the previous music streaming app example, a User can have multiple playlists. Each user can create as many playlists as they want, but each playlist is created by exactly one user.

As we can see, the approach is very similar to one-to-one relationship, the only difference here is in the relationship model(UserWithPlaylists). Instead of containing a single child entity, it now contains a list of child entity. Querying the database is also very similar.

Many-to-many relationships

A many-to-many relationship between two entities is a relationship where each instance of the parent entity corresponds to zero or more instances of the child entity, and vice-versa.

In the music streaming app example, each playlist can include many songs, and each song can be a part of many different playlists. Therefore, there should be a many-to-many relationship between the Playlist entity and the Song entity.

Many-to-many relationships are distinct from other relationship types because there is generally no reference to the parent entity in the child entity. Instead, a third class is used to represent an associative entity (or cross-reference table) between the two entities. The cross-reference table must have columns for the primary key from each entity in the many-to-many relationship represented in the table.

Now, the next step depends on how you want to query these related entities.

  • If you want to query playlists and a list of the corresponding songs for each playlist, create a new data class that contains a single Playlist object and a list of all of the Song objects that the playlist includes.
  • If you want to query songs and a list of the corresponding playlists for each, create a new data class that contains a single Song object and a list of all of the Playlist objects in which the song is included.

In either case, model the relationship between the entities by using the associateBy property in the @Relation annotation in each of these classes to identify the cross-reference entity providing the relationship between the Playlist entity and the Song entity.

Querying the database is similar to the previous approaches.

That’s all about the entity relationships in Room. Thank You!!!

--

--