During the last I/O, Google introduced Room, a persistence library which allows fluent database access while harnessing the full power of SQLite.

It’s true that the core framework already provides built-in support for working with SQL content, but although these APIs are powerful, they are fairly low-level and require a great deal of time and effort to use. Its major disadvantages are:

There is no compile-time verification of raw SQL queries, as your data graph changes, you need to update the affected SQL queries manually.

Lots of boilerplate code to convert between SQL queries and Java data objects.

Luckily for us, Google wants to make easier our programmer life and Room takes care of these concerns for you. Basically, Room is an abstraction layer over SQLite.

Room major components:

Entity: This component represents a class that holds a database row. For each entity, a database table is created to hold the items.

This component represents a class that holds a database row. For each entity, a database table is created to hold the items. DAO: This component represents a class or an interface as a Data Access Object (DAO). DAOs are the main component of Room and are responsible for defining the methods that access the database.

This component represents a class or an interface as a Data Access Object (DAO). DAOs are the main component of Room and are responsible for defining the methods that access the database. Database: is a holder class that uses annotation to define the list of entities and database version. This class content and defines the list of DAOs.

Room and Kotlin:

Let’s see how can we implement a Room database using Kotlin as a programming language:

Add Room dependencies in module build.gradle:

1 2 compile "android.arch.persistence.room:runtime:1.0.0-alpha5" kapt "android.arch.persistence.room:compiler:1.0.0-alpha5" Add Google’s Maven Repo in the project build.gradle:

1 2 3 4 5 6 allprojects { repositories { jcenter ( ) maven { url 'https://maven.google.com' } } } Create an Entity data class, for this, we need to annotate it with @Entity . By default, Room creates a column for each field that’s defined in the entity. If an entity has fields that you don’t want to persist, you can annotate them using @Ignore .



1 2 3 4 @Entity ( tableName = "user_table" ) data class User ( var created : Date = Date ( ) , var name : String = "" , @PrimaryKey var id : Int = 0 ) @PrimaryKey annotation. Also, we need to provide default values for all the fields. Create a DAO using an interface and the @Dao annotation :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Dao interface UserDao { @get : Query ( "SELECT * FROM user_table" ) val all : List <User> @Insert ( onConflict = OnConflictStrategy . REPLACE ) fun insert ( user : User ) @Delete fun delete ( user : User ) @Query ( "SELECT * FROM user_table" ) fun getLiveDataUsers ( ) : LiveData < List <User> > } When you create a DAO method and annotate it with @Insert , Room generates an implementation that inserts all parameters into the database in a single transaction. A method annotated with @Delete is a convenience method that deletes a set of entities, given as parameters, from the database. It uses the primary keys to find the entities to delete. @Query is the main annotation used in DAO classes. It allows you to perform read/write operations on a database. Each @Query method is verified at compile time, so if there is a problem with the query, a compilation error occurs instead of a runtime failure. Room also verifies the return value of the query such that if the name of the field in the returned object doesn’t match the corresponding column names in the query response it wont compile. Please note that we can return a LiveData result, Room generates all necessary code to update the LiveData when the database is updated. Create a Database holder that extends RoomDatabase. The class needs to be annotated with @Database annotation.

1 2 3 4 5 @Database ( entities = arrayOf ( User :: class ) , version = 1 , exportSchema = false ) @TypeConverters ( Converters :: class ) abstract class AppDatabase : RoomDatabase ( ) { abstract fun UserDao ( ) : UserDao } One thing I didn’t mention is that Room provides built-in support for primitives data types and their boxed alternatives. However, you sometimes use a custom data type whose value you would like to store in the database in a single column. To add this kind of support for custom types, you provide a TypeConverter, which converts a custom class to and from a known type that Room can persist. In our example, we need to convert the Date object. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Converters { @TypeConverter fun fromTimestamp ( value : Long ? ) : Date ? { return when ( value ) { null -> null else -> Date ( value ) } } @TypeConverter fun toTimestamp ( date : Date ? ) : Long ? { return when ( date ) { null -> null else -> date . time } } } Following the previous steps, we should be ready to start using the database. Remember that you must perform queries on a background thread, otherwise, your application will crash.Room Database instance is expensive, so we can create the AppDatabase object in the Application object and access it where need it or take the standard singleton approach. 1 2 3 4 5 6 7 8 9 10 11 12 class TestApplication : Application ( ) { lateinit var mDataBase : AppDatabase override fun onCreate ( ) { super . onCreate ( ) mDataBase = Room . databaseBuilder ( this , AppDatabase :: class . java , "database-name" ) . build ( ) } } 1 2 3 4 fun getTestApplicationContext ( ) : AppDatabase { return ( activity . applicationContext asTestApplication ) . mDataBase } 1 2 3 doAsync { users = getTestApplicationContext ( ) . UserDaoObject ( ) . all } or if you want to retrieve LiveData: 1 2 3 getTestApplicationContext ( ) . UserDaoObject ( ) . getLiveDataUsers ( ) . observe ( this , Observer < List <User> > { users -> items = users } )

This was a very simple example but enough to cover the syntax differences between Java and Kotlin, for more deeper information about Room, you can check this entry at Google’s Library but the code it’s all written in Java.

Conclusion:

As we just see, Room makes really easy the data persistence and solves the Android SQL core framework functions main problems. Also, with Room we can start forgetting about Object Relational Mapping libraries like Ormlite and even (with the LiveData combination) we can forget about Realm. What do you think about Room persistence library? You can leave your comment below. Thanks!

You can read the second part of the article here, Room Relationships