Room(四)
数据库版本迁移Migration
如果尝试直接在数据库中增加一个字段:
@Entity
public class Word {
@ColumnInfo(name = "foo_data")
private boolean foo;
public boolean isFoo() {
return foo;
}
public void setFoo(boolean foo) {
this.foo = foo;
}
}
在不做其它修改的情况下会爆出如下错误:
Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
如果只是将database中的版本改成高等级的:
@Database(entities = {Word.class},version = 2,exportSchema =false)
public abstract class WordDatabase extends RoomDatabase {
}
会爆出如下的错误:
Caused by: java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
这意味着我们需要去手动的做数据库的迁移,最简单的方式是破坏式迁移,在数据库构造器中加入语句:.fallbackToDestructiveMigration()
instance= Room.databaseBuilder(context.getApplicationContext(),
WordDatabase.class,"word_database")
.fallbackToDestructiveMigration()
.build();
如果想保留原先的列的数据,需要手动创建Migration,并用addMigrations传入:
@Database(entities = {Word.class},version = 4,exportSchema =false)
public abstract class WordDatabase extends RoomDatabase {
private static WordDatabase instance;
public static synchronized WordDatabase getDatabase(Context context){
if (instance==null){
instance= Room.databaseBuilder(context.getApplicationContext(),
WordDatabase.class,"word_database")
// .fallbackToDestructiveMigration()
.addMigrations(MIGRATION_3_4)
.build();
}
return instance;
}
public abstract WordDao getWordDao();
static final Migration MIGRATION_3_4 =new Migration(3,4) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("alter table word add column bar_data INTEGER not null default 1");
}
};
}
如果是要删除某一列,SQLite只能重新创建一张表来完成:
static final Migration MIGRATION_4_5 =new Migration(4,5) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("create table word_temp (id integer primary key not null,english_word text," +
"chinese_meaning text)");
database.execSQL("insert into word_temp (id,english_word,chinese_meaning)" +
"select id,english_word,chinese_meaning from word");
database.execSQL("Drop table word");
database.execSQL("alter table word_temp rename to word");
}
};