Search code examples
androidkotlinandroid-room

App crashes when trying to use a pre-populated room database due to difference between the schemes


I'm trying to make a small app for a project and decided to use a pre-populated database however i keep getting an error that says that the Expected and Found schemes are different, but i don't know what i need to do since the table names are the same, the type and name of the fields are also the same and they should be in the same position.

//Entity.kt
@Entity(tableName = "Book")
data class Book(
    @PrimaryKey(autoGenerate = true) val id: Int,
    @ColumnInfo val idImage: Int,
    @ColumnInfo val title: String,
    @ColumnInfo val author: String,
    @ColumnInfo val categories: String,
    @ColumnInfo val rating: Double,
    @ColumnInfo val discount: Int,
    @ColumnInfo val price: Double,
    @ColumnInfo val synopsis: String
)

//DAOs.kt
@Dao
interface BooksDao {
    @Query("SELECT * FROM book")
    fun getAll(): Flow<List<Book>>
}
//the table in the pre-populated database
CREATE TABLE "Book" (
    "id"    INTEGER NOT NULL,
    "idImage"   INTEGER NOT NULL,
    "title" TEXT NOT NULL,
    "author"    TEXT NOT NULL,
    "category"  TEXT NOT NULL,
    "rating"    REAL NOT NULL,
    "discount"  INTEGER NOT NULL,
    "price" REAL NOT NULL,
    "synopsis"  TEXT NOT NULL,
    PRIMARY KEY("id" AUTOINCREMENT)
);
//BooksDatabase.kt
@Database(entities = [Book::class], version = 1, exportSchema = true)
abstract class BooksDatabase : RoomDatabase() {
    abstract fun booksDao(): BooksDao
}

//BooksRepository.kt
class BooksRepository(private val booksDao: BooksDao) {
    val books: Flow<List<Book>> = booksDao.getAll()
}

//BooksViewModel.kt
data class BooksState(val books: List<Book>)

class BooksViewModel(private val repository: BooksRepository) : ViewModel() {
    val state = repository.books.map { BooksState(books = it) }.stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(),
        initialValue = BooksState(emptyList())
    )
}
//AppModule.kt
val AppModule = module {

    single {
        Room.databaseBuilder(
            get(),
            BooksDatabase::class.java,
            "books-list"
        ).createFromAsset("database/bookDatabase.db").build()
    }
    single { BooksRepository(get<BooksDatabase>().booksDao()) }
    viewModel { BooksViewModel(get()) }

}

//LibraryApplication.kt
class LibraryApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidLogger()
            androidContext(this@LibraryApplication)
            modules(AppModule)
        }
    }
}
@Composable
fun StoreScreen() {
    val booksVM = koinViewModel<BooksViewModel>()
    val bookState by booksVM.state.collectAsStateWithLifecycle()
}

When i go to the storeScreen the app immediately crashes and it gives me this error:

FATAL EXCEPTION: main Process: com.example.digitallibrary, PID: 7611 java.lang.IllegalStateException: Pre-packaged database has an invalid schema: Book(com.example.digitallibrary.data.database.Book).

Expected: TableInfo{name='Book', columns={author=Column{name='author', type='TEXT',affinity='2', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, price=Column{name='price',type='REAL', affinity='4', notNull=true,primaryKeyPosition=0,defaultValue='undefined'},rating=Column{me='rating', type='REAL', affinity='4', notNull=true,primaryKeyPosition=0,defaultValue='undefined'}, discount=Column{name='discount', type='INTEGER', affinity='3',notNull=true, primaryKeyPosition=0, defaultValue='undefined'},idImage=Column{name='idImage', type='INTEGER', affinity='3', notNull=true,primaryKeyPosition=0, defaultValue='undefined'}, id=Column{name='id',type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1,defaultValue='undefined'}, categories=Column{name='categories',type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, synopsis=Column{name='synopsis', type='TEXT',affinity='2', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, title=Column{name='title', type='TEXT',affinity='2', notNull=true,primaryKeyPosition=0,defaultValue='undefined'}}, foreignKeys=[], indices[]}
    Found:TableInfo{name='Book', columns={id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, idImage=Column{name='idImage', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, title=Column{name='title', type='TEXT',affinity='2', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, author=Column{name='author', type='TEXT',affinity='2', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, category=Column{name='category', type='TEXT',affinity='2', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, rating=Column{name='rating', type='REAL',affinity='4', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, discount=Column{name='discount', type='INTEGER',affinity='3', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, price=Column{name='price', type='REAL',affinity='4', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}, synopsis=Column{name='synopsis', type='TEXT',affinity='2', notNull=true, primaryKeyPosition=0,defaultValue='undefined'}}, foreignKeys=[], indices=[]}

I tried checking online but all the solutions are either really bare bone or just suggest to add the .createFromAsset() to the .build()


Solution

  • You will need to update your asset with a database whose schema matches what your code expects. Alternatively, update your code to match the schema of the database. Either way, those two need to agree on the columns and the column details (e.g., types).