Room database for Kotlin Multiplatform projects

Room database for Kotlin Multiplatform projects

Room(opens in a new tab) is a database library that uses SQLite(opens in a new tab) under the hood. In the past, it worked with Android only, but since adding support for all platforms, it works with Kotlin Multiplatform(opens in a new tab) (KMP) to store data in local databases on any platform supported by KMP.

This blog post will explore the process of integrating the Room database library into your Kotlin Multiplatform projects with ease and efficiency.

Setting up the Kotlin Multiplatform project

Navigate to the official Kotlin Multiplatform Wizard(opens in a new tab) and configure your platforms as per your needs.

For this demo, select the checkboxes for Android, iOS, and Desktop.

After selecting the platforms, select DOWNLOAD to download the ZIP file and extract the files.

You can open this project in either Android Studio(opens in a new tab) or IntelliJ IDEA(opens in a new tab)

Adding dependencies

Room version 2.7.0-alpha01 and higher includes support for Kotlin Multiplatform. This post uses Kotlin version 2.0.0 with Android Gradle plugin 8.2.2.

To add Room to your multiplatform project, include the dependencies below in libs.version.toml:

[versions]
room = "2.7.0-alpha03"
ksp = "2.0.0-1.0.21"
sqlite = "2.5.0-SNAPSHOT"
[libraries]
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
sqlite-bundled = { module= "androidx.sqlite:sqlite-bundled", version.ref = "sqlite" }
[plugins]
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
room = { id = "androidx.room", version.ref = "room" }

Now, you’ll add these to your build.gradle.kts file.

Append the plugins below in the plugins block and the dependencies below in the commonMain.dependencies block:

plugins {
alias(libs.plugins.ksp)
alias(libs.plugins.room)
...
commonMain.dependencies {
implementation(libs.room.runtime)
implementation(libs.sqlite.bundled)
...

Add the Room database schema path, along with KSP support for the Room compiler, at the end of the build.gradle.kts file:

room {
schemaDirectory("$projectDir/schemas")
}
dependencies {
// KSP support for Room Compiler.
kspCommonMainMetadata(libs.room.compiler)
}
// Solves implicit dependency issue and IDEs source code detection.
kotlin.sourceSets.commonMain { tasks.withType<KspTaskMetadata> { kotlin.srcDir(destinationDirectory) } }

You’ve now added all the required dependencies for Room to your KMP project.

Adding database classes

Next, create the Database class with DAOs and Entities inside the CommonMain package:

shared/src/commonMain/kotlin/Database.kt
@Database(entities = [FruitEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun getFruitDao(): FruitDao
}
@Dao
interface FruitDao {
@Upsert // Insert and update entities.
suspend fun upsert(fruit: FruitEntity)
@Delete
suspend fun delete(fruit: FruitEntity)
@Query("SELECT * FROM FruitEntity")
fun getAllAsFlow(): Flow<List<FruitEntity>>
}
@Entity
data class FruitEntity(
@PrimaryKey(autoGenerate = true) val id: Long = 0L,
val name: String,
val description: String,
val count: Int = 0
)

Next, add platform-specific code to create your database builder.

Android

shared/src/androidMain/kotlin/Database.kt
fun getDatabaseBuilder(context: Context) = with(context) {
val dbFile = applicationContext.getDatabasePath("room_android.db")
Room.databaseBuilder<AppDatabase>(
context = applicationContext,
name = dbFile.absolutePath
)
}

iOS

shared/src/iosMain/kotlin/Database.kt
fun getDatabaseBuilder() = Room.databaseBuilder<AppDatabase>(
name = NSHomeDirectory() + "/room_ios.db",
factory = { AppDatabase::class.instantiateImpl() }
)

Desktop

shared/src/commonMain/kotlin/Database.kt
fun getDatabaseBuilder() = Room.databaseBuilder<AppDatabase>(
name = File(System.getProperty("java.io.tmpdir"), "room_desktop.db").absolutePath
)

Here’s the database builder you use to initialize your AppDatabase:

shared/src/commonMain/kotlin/Database.kt
fun getRoomDatabase(builder: RoomDatabase.Builder<AppDatabase>): AppDatabase {
return builder
.addMigrations(MIGRATIONS)
.fallbackToDestructiveMigrationOnDowngrade()
.setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.build()
}

At last, the Room database setup is complete! Now, with the getRoomDatabase method, you can easily retrieve the database instance.

Conclusion

This post demonstrated how only a few lines of code can grant the power of databases in multiple platforms in a single codebase. With the instance of AppDatabase, it’s possible to perform all database transactions — like searching, inserting, and deleting data — regardless of which platform you’re on. Magic!

For a working example project of Room database implementation in KMP, refer to the following GitHub repository(opens in a new tab).

FAQ

What are the advantages of using Room in Kotlin Multiplatform projects?

Room simplifies database management with a clean API and provides compile-time checks for SQL queries, enhancing code reliability across platforms.

How does Room handle database migrations?

Room manages migrations through defined migration paths, allowing developers to upgrade the database schema seamlessly without losing existing data.

Can Room be used for both local and remote data storage?

While Room is primarily designed for local database storage using SQLite, it can be integrated with other libraries to facilitate remote data synchronization.

What is the importance of using Kotlin Multiplatform?

Kotlin Multiplatform enables code sharing across different platforms (like Android and iOS), reducing development time and maintaining consistency in codebases.

Is Room suitable for handling large datasets?

Yes, Room is efficient for managing large datasets, but performance can depend on how well the database is structured and the complexity of the queries.

Akshay Sharma

Akshay Sharma

Senior Android Engineer

Akshay is an open source enthusiast who loves creating mobile apps and traveling to new places. He usually spends his free time with his family.

Explore related topics

FREE TRIAL Ready to get started?