Романыч
Романыч

Reputation: 287

Room fallbackToDestructiveMigration

I get acquainted with Room and try to assemble a small project by reading the database from the ASSETS folder. Faced such a question: When one version of the database is thrown, it throws an exception and asks to add MIGRATION. It’s enough for me to simply rewrite the database from assets when raising the version. There is a fallbackToDestructiveMigration () method in the docks for this purpose. But when I specify it in the builder, in fact my database is overwritten every time the application starts. What I need is for the database to be rewritten from assets only when the application version is raised. and I don’t understand how to achieve this behavior. I would be grateful for your help.

This is how I do everything:

This is the simplest example.

DAO:

 @Dao
NameDao
@Insert(entity = Name.class, onConflict = OnConflictStrategy.REPLACE)
void insertMe(Name name);

Database

    @Database(version = 2, entities = [Name::class])
abstract class AppDatabase : RoomDatabase() {
    abstract fun nameDao(): NameDao
}

POJO Entity

@Entity(tableName = "tips_of_the_day")
data class Name(
    @ColumnInfo(name = "name")
    var name: String?
) {
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "_id")
    var id: Int = 0
}

Application class

class App : Application() {
private lateinit var appDatabase: AppDatabase


override fun onCreate() {
    super.onCreate()
    appDatabase = getAppDatabase()
}

 fun getAppDatabase(): AppDatabase {

    return Room.databaseBuilder(
        this,
        AppDatabase::class.java, DATABASE_NAME
    )
        .createFromAsset("database/tips_of_the_day.db")
        .fallbackToDestructiveMigration()
        .allowMainThreadQueries()
        .build().also { appDatabase = it }

}

companion object {
    private const val DATABASE_NAME = "tips_of_the_day.db"
}
}

AND MY ACTIVITY

val db: AppDatabase = (application as App).getAppDatabase()
    val dataBase = db.nameDao()


    textView.setOnClickListener(){
        val name: Name = Name( "Anton")
        dataBase.insertMe(name)
        val tableSize: Int = dataBase.all.size
        toast("db size  : $tableSize")
        Log.d("TAG" , "db size  : $tableSize")
    }

It turns out that the code works until the application is restarted and then the database is overwritten by default and becomes new (

I did not want this behavior. I need to save the database until the version is up. How to achieve this?

Upvotes: 0

Views: 2950

Answers (1)

sergiy tykhonov
sergiy tykhonov

Reputation: 5103

I know it may seemed like a dirty way to solve your problem, but you can manage migrate-or-not issue manually:

fun getAppDatabase(context: Context): AppDatabase {
        // is migration really needed?
        val db = SQLiteDatabase.openDatabase(context.getDatabasePath(DATABASE_NAME).path, null, SQLiteDatabase.OPEN_READONLY)
        val needToMigrate = db.version < dbVersion // your actual version, could be constant
        db.close()
        return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
            .allowMainThreadQueries().apply {
            if (needToMigrate) this.createFromAsset(DATABASE_DIR)
                .fallbackToDestructiveMigration()
        }.build()
    }

Upvotes: 1

Related Questions