← All articlesExploring Room Architecture component — The Extras
9 December 2017·Originally on Medium

SQL queries (Credits)

Exploring Room Architecture component — The Extras

Content

Preface

In this article we will be exploring “extras” aka extra features of Room library.

In case you are not aware about Room then check out my previous article Exploring Room architecture component or if you don’t know about architecture components then head on to Introduction to Android Architecture Components.

Transaction support

Room by default runs queries like insert, update and delete in a transaction. But in order to run other queries like select query or when running multiple queries in a single transaction, the Transaction annotation has been introduced since 1.0.0-rc1.

It marks the function in the Dao class as transaction function in order to execute it in a transaction.

Multiple queries

Sometimes we want to perform multiple operations on the database. Let’s say I want to insert a new record and update the record at the same time, by default these both operations will run in their own transaction which might lead to inconsistency (in case if the 1st operation is successful and 2nd one fails).

In those situations we can create a non-abstract function containing both the operations and executing it in a single transaction by marking it with Transaction annotation.

View the code on GitHub Gist

Here, the insertAndUpdate function runs in a single transaction and inserts a new user and immediately updates the user’s name to all CAPS.

For @Query

There are 2 main use-cases to use the transaction annotation with select query:

  1. When the result of the query is big, it’s better to run it in transaction for consistent result
  2. When the result of the query is a POJO (most likely Embedded) with Relation fields, these fields are queried separately. Hence it’s better to run it in a transaction to receive consistent results between these queries.

Read more about @Transaction and @Query:

Transaction | Android Developers

RxJava support

Room supports RxJava2 to perform reactive queries out-of-the box which is like yay for Rx fans or people who are already using RxJava in their applications.

Features

  • It supports Maybe, Single and Flowable types to perform observable queries.
  • The observable / reactive queries are performed on the background thread.
  • It’s easier to test, almost similar to testing synchronous queries

Adding it to the project

To add RxJava support with Room in your project, you need to add an additional dependency

// RxJava2 support for Room
implementation "android.arch.persistence.room:rxjava2:1.0.0"

Read more about RxJava support:

Room 🔗 RxJava

Indexing

Indexing is the process of adding indexes which are used to quickly locate data without having to search every row in a database table every time the database table is queried or accessed.

Room supports indexing certain fields or indexing group of fields using indices property to speed up the queries.

Adding an index

To add an index we use the indices property in Entity annotation. It contains the list of the columns to index.

View the code on GitHub Gist

As the indices property takes variable number of parameters, we can have group of indexes or multiple indexes.

View the code on GitHub Gist

PS: With Kotlin 1.2 we can write array directly using [] instead of using the arrayOf function for more conciseness

The indexes can be marked as unique (by default it is false)using the unique property in the Index definition, which enforces uniqueness.

Embedded index

We create an Embedded class when working with Relation in Room. The indexes of embedded entity or entities are not carried forward to the Embedded class.

We need to explicitly re-mention the required indexes in the Embedded class

Inheriting indexes

Room even supports inheriting indexes from parent class which are carried over to the current Entity using the special property called inheritSuperIndices which takes a boolean value.

By default, the value of the property is false. On setting it to true all the indexes from parent class are carried to the current Entity.

Note that even if the Entity has a parent which sets this value to false, the Entity will still inherit indices from it and its parents.

Indexing usually speeds up the select queries but slows down the other queries like insert, update and delete. Hence make sure to use indexing where it is really required

Type Converter

Room supports basic data types but sometimes these are not sufficient. At such times we require custom data types to be stored in the database. That’s when TypeConverter comes in to rescue!

TypeConverter specifies how the conversion happens between Java / Kotlin object to it’s database equivalent which helps Room in deciding how to save the custom data type in the database.

View the code on GitHub Gist

Here, the DateConverters class is to tell Room how to store and retrieve date from SQLite database. The Date object is stored as Long in the database and while retrieving it is converted back to Date object.

Don’t get confused with TypeConverter and using Relation. They serve different purpose.

Note: TypeConverter offers only 1 to 1 mapping between Java field / Kotlin property to SQLite column.

Conclusion

In a nutshell, Room offers a lot of features which is why I needed to write one more article on it.

With this article, we mark the ending of deep dive of Architecture Components series. In the next parts we will explore how to use Architecture Guidelines and Components to build robust, testable and maintainable apps.


Exploring Room Architecture component — The Extras was originally published in ProAndroidDev on Medium, where people are continuing the conversation by highlighting and responding to this story.