Room Database in Android – Simplifying SQLite Database Access - Textnotes

Room Database in Android – Simplifying SQLite Database Access


Learn how to use Room Database, a persistence library in Android that simplifies SQLite database operations by providing an abstraction layer. It uses Entities for tables and DAOs for data operations, making database interactions more efficient and easy to manage.

Room is an SQLite library provided by Jetpack for Android development. It simplifies database access by using entities for tables and DAO (Data Access Object) interfaces for data operations, reducing boilerplate code and handling database migrations smoothly.

i) What is Room Database?

Room is a persistence library that provides an abstraction layer over SQLite, making database access more efficient and less error-prone. It simplifies many aspects of working with SQLite, including data persistence, migrations, and querying.

ii) Key Components of Room

  1. Entities:
  2. Entities are classes that represent tables in the database. Each entity corresponds to a table, and the fields in the entity correspond to the columns in the table.
  3. You define an entity by annotating a class with @Entity.
  4. Example:

@Entity(tableName = "user_table")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "age") val age: Int
)
  1. In this example:
  2. The User class represents a table in the SQLite database called user_table.
  3. The id field is the primary key for the table.
  4. name and age represent columns in the table.
  5. DAO (Data Access Object):
  6. DAO provides methods for accessing the database. You use DAO interfaces to define methods for querying, inserting, updating, and deleting data from the database.
  7. DAOs are annotated with @Dao and define methods annotated with @Insert, @Update, @Delete, @Query, etc.
  8. Example:

@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)

@Update
suspend fun update(user: User)

@Delete
suspend fun delete(user: User)

@Query("SELECT * FROM user_table WHERE id = :id")
suspend fun getUserById(id: Int): User?
}
  1. In this example:
  2. The UserDao interface defines methods to insert, update, delete, and query the User entity.
  3. @Insert, @Update, @Delete, and @Query are used to define the database operations.
  4. Database:
  5. The RoomDatabase class provides the database holder and serves as the main access point for the underlying SQLite database.
  6. It is annotated with @Database and includes the entities and DAOs that define the database schema and operations.
  7. Example:

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
  1. In this example:
  2. AppDatabase is a RoomDatabase class that includes the User entity and the UserDao.
  3. The version number is important for managing database migrations.
  4. DatabaseBuilder:
  5. You use Room.databaseBuilder to create an instance of your Room database.
  6. Example:

val db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "app_database")
.fallbackToDestructiveMigration() // Optional: handles migrations if schema changes
.build()
  1. This code creates a Room database instance. You can access it in your app to interact with the database.

iii) Using Room in Your Android App

Let’s go through a complete example of using Room to handle a simple User entity in an Android app.

Step 1: Add Room dependencies

Add the following dependencies to your build.gradle file:


dependencies {
implementation "androidx.room:room-runtime:2.4.0" // Room Database
kapt "androidx.room:room-compiler:2.4.0" // Room Compiler for annotation processing
}

Make sure to add kapt if you're using Kotlin.

Step 2: Define the Entity

Create a User data class that will represent the user_table:


@Entity(tableName = "user_table")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "age") val age: Int
)

Step 3: Create a DAO

Define a DAO interface for the User entity:


@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)

@Query("SELECT * FROM user_table")
suspend fun getAllUsers(): List<User>
}

Step 4: Create the Database

Create a RoomDatabase subclass to serve as the database holder:


@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}

Step 5: Initialize the Database

Initialize the Room database in your Activity or Application class:


val db = Room.databaseBuilder(
applicationContext, AppDatabase::class.java, "user_database"
).build()

val userDao = db.userDao()

Step 6: Interact with the Database

Now, you can use the UserDao to insert and query data:


GlobalScope.launch(Dispatchers.IO) {
val user = User(0, "John Doe", 30)
userDao.insert(user) // Insert user into the database

val users = userDao.getAllUsers() // Retrieve all users from the database
users.forEach {
Log.d("User", "Name: ${it.name}, Age: ${it.age}")
}
}

iv) Migrations

When you change the schema of your database (e.g., adding or modifying tables), you need to handle migrations. Room provides a Migration class to help with this.

Example of migration:


val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
// Add new columns or alter tables here
database.execSQL("ALTER TABLE user_table ADD COLUMN email TEXT")
}
}

You can pass the migration to Room.databaseBuilder like this:


val db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "user_database")
.addMigrations(MIGRATION_1_2)
.build()

v) Benefits of Room Database

  1. Abstraction Over SQLite:
  2. Room simplifies working with SQLite by providing an abstraction layer. You don’t have to write raw SQL queries for most common database operations.
  3. Compile-time Checking:
  4. Room provides compile-time verification of SQL queries, helping to avoid runtime errors and ensuring query correctness.
  5. Database Migration:
  6. Room makes it easy to manage database schema changes by providing a migration API that handles version updates.
  7. Integration with LiveData:
  8. Room seamlessly integrates with LiveData, allowing you to observe database changes and update the UI automatically when data changes.

vi) Conclusion

In this tutorial, we’ve learned about Room Database, which provides an abstraction layer over SQLite and simplifies database operations in Android. Room helps:

  1. Reduce boilerplate code for database operations.
  2. Provide compile-time checking of queries.
  3. Easily manage database migrations.
  4. Integrate with LiveData for lifecycle-aware UI updates.

By using Room, Android developers can focus more on app logic and less on handling low-level database details, making database interactions more efficient and less error-prone.