Android Room Persistence Library: Relations in a Nested One-To-Many Relationship.

Ikhiloya Imokhai
Oct 24, 2019 · 5 min read
Image for post
Image for post
source: Android Developers Blog

Relation is a convenience annotation which can be used in a Pojo to automatically fetch relation entities. When the Pojo is returned from a query, all of its relations are also fetched by Room.

The type of the field annotated with Relation must be a List or Set. By default, the Entity type is inferred from the return type.

There are tons of resources on Room persistence library, you might want to check them out.

The scenario we would explore in this article is that of a hypothetical publishing company that has several authors whose books they publish. Furthermore, these Authors may have one or more Books published by the publishing firm.
The above relationship can be best described as a nested one-to-many relationship. That is, the Publisher entity has a one-to-many relationship with the Author entity which also maintains a one-to-many relationship with the Book entity.

Image for post
Image for post

Thankfully, we can model this relationship using Room persistence library which is part of the android architecture components. Using Room, we can have three entities and then specify the relationships using foreign keys.

The complexity arises when we try to query for the Publisher entity and then expect to get all of its relation entities i.e. its list of Authors, as well as the list of Books for each author.

How then do we solve this complexity?

The first approach that comes to mind is to query for the publisher entity, get its id and then go to the Author entity and query for all authors using the publisher id. Also, for every author, we’d need to also use the author id to query for all books with an author id. Heck! You can see the level of complexity using this approach as the queries and loops might have a performance overhead.

Relation to the Rescue
The second and by far a more efficient approach is to use Relation annotation to query for the entity relationship.

For our use case, we need to create two Pojos called PublisherDetails and AuthorBookDetails in which all fields are fetched from the entity defined in the Relation annotation.

Note that @Relation annotation can be used only in Pojo classes, an Entity class cannot have relations.

Notice how we’ve used the @Embedded annotation for both the Publisher and Author entities to signal that there are nested fields and as such Room will properly construct the Publisher and Author class.

Also notice, how the parentColumn , entityColumn and entity are used.

Let’s understand their meanings:

  1. entity : This is the entity to fetch from. For the PublisherDetails pojo, this is the Author entity while for the AuthorBookDetails pojo, it is the Book entity.
  2. parentColumn: This is a reference field in the parent pojo, say the PublisherDetails or AuthorBookDetails pojo. This is particularly useful when you want to access a sub-item of an embedded field. For instance, in the PublisherDetails pojo, notice that the Publisher entity is Embedded. So setting the parentColumn to id means we want to access the id of the embedded Publisher entity i.e. publisher.id . Same explanation holds for the AuthorBookDetails pojo.
  3. entityColumn: This is the field path to match in the entity. This value will be matched against the value defined in parentColumn. For the PublisherDetails pojo the entityColumn references the publisherId of the Author entity. Recall that the Author entity has a relationship with the Publisher entity via the publisherId foreign key. So, what happens here is that the id of the embedded Publisher entity referenced by the parentColumn (publisher.id) is matched with the publisherId(foreign key) on the Author entity as specified by the entity field. By doing this a relationship is established between the Publisher and Author entity and the results are returned to the List as specified in the relation. Same explanation holds for the AuthorBookDetails pojo.

Next is to write a dao query method to fetch the Publisher entity, but this time the return object would be the PublisherDetails pojo (by default, inferred from the the return type).

If we observe the LiveData returned from the query above, we’d get a list of PublisherDetails object. Calling a toString() on the list gives the following:

toString() representation of PublisherDetails pojo

From the above, we can see that the object relationship is not what we want. That is, the PublisherDetails pojo contains a publisher object with authors as null while the AuthorBookDetails pojo contains an author object with books as null.

So we need a way to get the single object relationship we require. For this we need to create constructors in the Publisher and Author entities which would handle the mapping of the PublisherDetails to the Publisher and Author entities respectively. This would eliminate null values and build a single object relationships between the entities.

Add the following to the Publisher entity:

Using the constructor above, we can use Java 8 stream functionality to create our desired object structure like so:

From the above, we can now get a single Publisher object that contains a list of authors as well as list of books for each authors. A toString() on the the list of publishers would yield:

toString() representation of Publisher entity

So that’s it. By using Relation annotation on pojos, you can automatically fetch relation entities. You can check out the code here.

Also you can check this article by Reza Bigdeli for another approach using Relation with LiveData.

Do well to drop your comments, feedback or a better approach for this kind of problem.

Thanks.

  1. Room Persistence Library
  2. Relation
  3. Android Room Persistence Library: Relations by Magda Miu
  4. Android Room: Handling Relations Using LiveData by Reza Bigdeli

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Ikhiloya Imokhai

Written by

Software Developer | imokhaiikhiloya@gmail.com | https://github.com/Ikhiloya | open to exciting projects

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Ikhiloya Imokhai

Written by

Software Developer | imokhaiikhiloya@gmail.com | https://github.com/Ikhiloya | open to exciting projects

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store