Android has introduced Architecture Component that has Room Library for managing SQLite database. Here I will provide a step by step guide to implement the Room persistent library. If you are a beginner you can easily follow along. And even if you are seasoned developer, this will refresh your knowledge.
Quick Navigation
What is Room Persistence Library ?
Room Persistence Library (RPL) is an ORM introduced for Android X. It is simply an abstraction layer over existing SQLite implementation which Android provides.
Which means you do not have to worry about all the boilerplate code that goes under to manage SQLite. You can just easily access the database with nice looking API endpoints.
It will save you time and make your code look really clean. It also makes sure there are no surprise crashes in your application with the compile time check.
Adding room dependency
Before we can continue with our code we have to add the following dependency in the app > build.gradle
file and do a gradle sync ( File > Sync project with gradle files
)
Add the line below in the app > build.gradle
file.
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
Code language: Groovy (groovy)
Make sure you have kotlin-kapt
if you are using Kotlin
, if not you must add kotlin-kapt
at the top below kotlin-android
plugin. Shown in image below.
And if you are using Java
implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor "androidx.room:room-compiler:2.2.5"
Code language: Groovy (groovy)
Also Read: Android RecyclerView: How to Insert, Update and Delete Item
TECHENUM
Setting up Room library
Now that we have included the library let us first setup the database class which we will be using.
I have created a dead simple diagram trying to explain the flow. Look at the image below
Now that you have looked at the database. There are two things you must understand Entity and the DAO. These both are annotation which we will look at later.
Let us first setup the main class we will be accessing.
@Database(entities = [ExampleEntity::class], version = 1, exportSchema = false)
abstract class MyDatabase : RoomDatabase() {
abstract fun exampleDao(): ExampleDao
companion object {
private lateinit var MY_DATABASE_INSTANCE: MyDatabase
fun instance(application: Application): MyDatabase {
if (!::MY_DATABASE_INSTANCE.isInitialized)
MY_DATABASE_INSTANCE =
Room.databaseBuilder(application, MyDatabase::class.java, "my_database.db")
.build()
return MY_DATABASE_INSTANCE
}
/**
* This instance is for getting the database without passing an application instance.
* As we have the singleton pattern passing the application instance every time is redundant.
*/
fun instance(): MyDatabase {
return MY_DATABASE_INSTANCE
}
}
}
Code language: Kotlin (kotlin)
Everything is just normal Kotlin code, just look at
@Database(entities = [ExampleEntity::class], version = 1, exportSchema = false)
Code language: Kotlin (kotlin)
The Database
is an annotation where entities
are all the tables.
The version
must be incremented each time you have updated the overall database structure. Meaning if you have added or removed any table from the database.
The exportSchema
is the overall database structure provided by the RPL. Generally it can be flagged false.
Now that we have successfully setup the Android Room library for SQLite database. Let us move on to setting up our library.
Also Read: Android Content URI: How to Get the File URI
TECHENUM
Setting up Entity in Room
What is the Entity ?
The Entity is nothing more than a simple Class
that represents SQLite database’s table. We define a normal Class
and the RPL will automatically convert it into the table SQL query and implement it.
The Class
will contain all the columns which are in the database. We will see this here.
See the code below
@Entity
data class ExampleEntity(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(name = "column_one", defaultValue = "-")
val columnOne: String = "",
val columnTwo: String = ""
)
Code language: Kotlin (kotlin)
You must always keep in mind that the class should be annotated @Entity
. The class must have at least one member variable annotated with @PrimaryKey
.
Additionally you can also change the name of the column in the actual table using annotation @ColumnInfo
.
As this is just an introduction you should see the official documentation if you want more info on each annotation.
That is it for the Entity
. You must add the entity to the entities
array in @Database
annotation each time you create a new Entity
. And then increase the version of the database by at least +1
.
Setting up DAO in Room
What is DAO ?
DAO is simply an interface
from which the Room compiler will create a concrete class from. This class will include the SQL Queries for the database.
Look at the code below, notice that it is an interface annotated with @Dao
@Dao
interface ExampleDao {
@Insert
fun insert(entity: ExampleEntity)
@Insert
fun insert(entities: List<ExampleEntity>)
@Update
fun update(entity: ExampleEntity)
@Update
fun update(entities: List<ExampleEntity>)
@Delete
fun delete(entity: ExampleEntity)
@Delete
fun delete(entities: List<ExampleEntity>)
@Query("SELECT * FROM exampleentity WHERE column_one=:someValue")
fun query(someValue: String): List<ExampleEntity>
}
Code language: Kotlin (kotlin)
I have provided an example for @Insert
, @Update
, @Delete
and @Query
.
I hope the code is self explanatory. You can create your custom queries using the @Query
annotation. Everything else is just as simple.
After create a DAO we must add it to class that extends RoomDatabase
in our case the MyDatabase
class. The following code is already present.
abstract fun exampleDao(): ExampleDao
Code language: Kotlin (kotlin)
You must add an abstract method for each DAO you create.
Also Read: Kotlin Coroutine in Android : Understanding the Basics
TECHENUM
Using the Room library
Now let us see how we can use it. We cannot simply perform operations on the main thread. The application will crash if we do so.
Let us use AsyncTask
for quickly running our code. But note that AsyncTask
is deprecated and you should not use it anymore. Read why here: Async Task in Android is Deprecated: There are Better Ways.
But to keep the explanation readable let me quickly use it for the sake of demonstration.
Insert
To insert a new Entity in the database you run the code below
private fun insert() {
AsyncTask.execute {
val entity = ExampleEntity(0, "Example String", "techenum.com")
val db = MyDatabase.instance(application)
db.exampleDao().insert(entity)
}
}
Code language: Kotlin (kotlin)
Since the id
is automatically incremented we do not have to keep track of it.
Update
For updating the value let us see code below. Updating is done using the primary key so let us use id = 1
.
private fun update() {
AsyncTask.execute {
val entity = ExampleEntity(1, "Updated String", "techenum.com")
val db = MyDatabase.instance(application)
db.exampleDao().insert(entity)
}
}
Code language: Kotlin (kotlin)
Delete
Removal is also done using the primary key of the Entity
. In our case let use again use the id = 1
.
private fun delete() {
AsyncTask.execute {
val entity = ExampleEntity(1, "Updated String", "techenum.com")
val db = MyDatabase.instance(application)
db.exampleDao().insert(entity)
}
}
Code language: Kotlin (kotlin)
Custom query
Let us see how we can execute the custom query that we have defined earlier
private fun customQuery() {
AsyncTask.execute {
val db = MyDatabase.instance(application)
db.exampleDao().query("some value")
}
}
Code language: Kotlin (kotlin)
We have just passed in "some value"
for the column_one
field in the database.
If you have any questions regarding the android Room Persistence Library for SQLite database.