Android

Android JetPack学习总结(九)

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");
        }
    };

发表评论