2

I have a Kotlin project for desktop which uses Room DB. The main function looks like this:

import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.driver.bundled.BundledSQLiteDriver

@Database(version = 1)
abstract class MyRoomDatabase : RoomDatabase()

fun main() {
    val db = Room.databaseBuilder<MyRoomDatabase>("database.db")
        .setDriver(BundledSQLiteDriver())
        .build()

    db.runInTransaction {
        // something
    }
}

It creates an empty database without any DAOs or entities.

Then I try to run the runInTransaction method, but my IDE and the compiler can't find it.

However this method should exist, it is mentioned in the docs here.

It should be available for all instances of RoomDatabase and since MyRoomDatabase inherits from RoomDatabase, it should have that method.

Any idea why it is missing??

Here's my build file:

plugins {
    kotlin("jvm") version "2.2.0"
    id("com.google.devtools.ksp") version "2.2.0-2.0.2"
    application
}

repositories {
    mavenCentral()
    google()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
    testImplementation(kotlin("test"))

    // Room DB
    val roomVersion = "2.7.2"
    implementation("androidx.room:room-runtime:$roomVersion")
    ksp("androidx.room:room-compiler:$roomVersion")
    implementation("androidx.sqlite:sqlite-bundled:2.5.2")
}

kotlin {
    jvmToolchain(23)
}

application {
    mainClass.set("MainKt")
}

I'm using version 2.7.2 of room which should definitely have that method implemented.

Also, a lot of the other public methods such as clearAllTables or compileStatement are missing.

And this is not because the database is empty or has no DAOs, it didn't work in my actual project which has data.

Hope you have any idea

Thank you and have a nice day

Edit: Replit project to reproduce the error https://replit.com/@axolotlKing07/Reproducing-Room-DB-method-missing?v=1

2
  • What type does the IDE and compiler think db is? Commented Sep 7 at 11:37
  • @CommonsWare MyRoomDatabase which inherits from RoomDatabase Commented Sep 7 at 12:09

2 Answers 2

1

Check the docs again:

https://developer.android.com/reference/androidx/room/RoomDatabase#runInTransaction(java.util.concurrent.Callable)

It says following:

If a SQLiteDriver is configured with this database, then it is best to use useWriterConnection along with immediateTransaction to perform transactional operations.

It is expected that the function you try to use is not working in a jvm environment. (Although wording is really a bit unclear).

Solution

https://developer.android.com/kotlin/multiplatform/room#transactions

Copied from the docs:

val database: RoomDatabase = …
database.useWriterConnection { transactor ->
  transactor.immediateTransaction {
    // perform database operations in transaction
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Ok thanks I saw that one too but still wondered why the method is not present at all, because it doesn't say so in the docs. Also there are a lot of other public methods which are also missing. But this should solve my problem thank you
0

As the documentation of runInTransaction you linked explains, when using SQLiteDriver you should use useWriterConnection instead. That is also explained in more detail in the KMP migration guide for Room:

db.useWriterConnection { transactor ->
    transactor.immediateTransaction {
        // perform database operations in transaction
    }
}

Note that useWriterConnection is now properly marked as a suspend function, so you have to call it from a coroutine (this is necessary so the database access can be moved to the IO dispatcher internally, making this function main-safe).

The alternative is to move the transaction to the DAO:

@Dao
interface MyDao {
    @Transaction
    fun myTransaction() {
        // ...
    }
}

You can call other DAO functions in myTransaction, guaranteeing that they are executed atomically (i.e. all of them successfully, or none at all).

As for the other methods, they are also not availble when using SQLiteDriver. I don't know of a ready-to-use alternative, although compileStatement shouldn't even be necessary when using DAOs.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.