Home > Software engineering >  Room livedata : crash on launch
Room livedata : crash on launch

Time:07-05

Recently I've decided to start using LiveData in my Room database by adding it to ado methods and then observing them in ViewModel, then even though I updated DB version after making all the changes and made a migration, it throws this error on emulator launch

2022-07-03 15:35:17.723 4866-4891/com.example... E/SQLiteLog: (1) statement aborts at 1: [ROLLBACK;] cannot rollback - no transaction is active
2022-07-03 15:35:17.724 4866-4891/com.example... E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0
    Process: com.example..., PID: 4866
    java.lang.RuntimeException: Exception while computing database live data.
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:920)
     Caused by: android.database.sqlite.SQLiteException: cannot rollback - no transaction is active (code 1 SQLITE_ERROR)
        at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
        at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:709)
        at android.database.sqlite.SQLiteSession.endTransactionUnchecked(SQLiteSession.java:441)
        at android.database.sqlite.SQLiteSession.endTransaction(SQLiteSession.java:403)
        at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:589)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:422)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:151)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:112)
        at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:706)
        at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:483)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:526)
        at androidx.room.util.DBUtil.query(DBUtil.java:86)
        at com.example...data.database.NoteDao_Impl$16.call(NoteDao_Impl.java:723)
        at com.example...data.database.NoteDao_Impl$16.call(NoteDao_Impl.java:720)
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:920) 

My dao code :

@Dao
interface NoteDao {

    @Delete
    fun deleteFolder(folder: Folder)

    @Query("UPDATE Note SET isStarred = :state WHERE id = :id")
    fun updateNoteChecked(id : Int, state : Boolean)

    @Query("DELETE FROM Note WHERE id = :id")
    fun deleteNoteById(id : Int)

    @Query("SELECT * FROM Note WHERE id = :id")
    fun getNoteById(id : Int) : Note

    @Query("SELECT title FROM Folder WHERE id = :id")
    fun getFolderTitleById(id : Int) : String

    @Query("SELECT * FROM folder WHERE id = :id")
    fun getFolderById(id : Int) : Folder

    @Query("UPDATE Folder SET title = :title WHERE id = :id")
    fun updateFolderTitle(id : Int, title : String)

    @Query("SELECT * FROM Folder WHERE id = :id")
    fun getFolderWithNotesByFolderId(id : Int) : FolderWithNotes

    @Query("SELECT * FROM Note WHERE folderId = :id ORDER BY isStarred")
    fun getNotesByFolderId(id : Int) : LiveData<List<Note>>

    @Query("SELECT * FROM note WHERE content LIKE :query ORDER BY isStarred")
    fun searchAllNotes(query : String?) : LiveData<List<Note>>

    @Query("SELECT * FROM note WHERE folderId = :id AND content LIKE :query ORDER BY isStarred" )
    fun searchNotesByFolderId(query : String?, id : Int) : LiveData<List<Note>>

    @Query("SELECT * FROM Note ORDER BY isStarred")
    fun getAllNotes() : LiveData<List<Note>>

    @Query("SELECT * FROM  Folder WHERE id = :id")
    fun getFolderWithNotes(id : Int) : List<FolderWithNotes>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertFolder(folder : Folder)

    @Query("SELECT * FROM Folder")
    fun getAllFolders() : LiveData<List<Folder>>

    @Query("UPDATE folder SET noteCount = noteCount   1 WHERE id = :id")
    fun updateOnInsertNote(id : Int)

    @Query("UPDATE folder SET noteCount = noteCount - 1 WHERE id = :id")
    fun updateOnDeleteNote(id : Int)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertNote(note : Note)

    @Delete
    suspend fun deleteNote(note : Note)
}

Database class :

@Database(entities = [Note::class, Folder::class] , version =  11 )
abstract class NoteDatabase : RoomDatabase() {
    abstract fun NoteDao() : NoteDao
}

Data base hilt provide method :

@Provides
    @Singleton
    fun provideNoteDatabase(app : Application) : NoteDatabase{
        return Room.databaseBuilder(
            app ,
            NoteDatabase::class.java,
            "notes",

        ).fallbackToDestructiveMigration()
            .addCallback(DatabaseCallback())
            .build()
    }

CodePudding user response:

As per my comment, I suspect that the issue is within the callback (DatabaseCallback) and probably in the overidden onOpen method.

The reasoning is that the trace shows:-

  • that you have issued a query as per at androidx.room.RoomDatabase.query(RoomDatabase.java:526)
  • that this successfully opens the database as per at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316) -and then appears to end a transaction (without committing the transaction). As Room is proven, then the most likely issue is that an attempt is being made to end a transaction when no transaction has been started and thus, due to the lack of the commit, there is nowhere/nothing to rollback to.
  • Related