Room數(shù)據(jù)庫(kù)版本升級(jí),數(shù)據(jù)遷移詳解

一、背景介紹

使用SQLite API執(zhí)行數(shù)據(jù)庫(kù)遷移總有一種是在拆彈的感覺-仿佛一不小心就會(huì)讓app在用戶手中爆炸。如果你使用Room來處理數(shù)據(jù)庫(kù)的操作,那么遷移就非常簡(jiǎn)單了。
使用Room的時(shí)候,如果你改變了數(shù)據(jù)庫(kù)的schema但是沒有更新version,app將會(huì)crash。而如果你更新了version但是沒有提供遷移,數(shù)據(jù)庫(kù)的表就會(huì)drop掉,用戶將丟失數(shù)據(jù)。

二、數(shù)據(jù)庫(kù)遷移背后的原理

QLite數(shù)據(jù)庫(kù)處理schema的改變是在database version的幫助下完成的。更準(zhǔn)確的說,每當(dāng)你添加,刪除,或者修改表導(dǎo)致schema變化的時(shí)候,你都必須增加數(shù)據(jù)庫(kù)的版本號(hào)并更新SQLiteOpenHelper.onUpgrade方法。當(dāng)你從舊版本到新版本的時(shí)候,是它告訴SQLite該做什么。
它也是app開始和數(shù)據(jù)庫(kù)工作是所觸發(fā)的第一個(gè)調(diào)用。SQLite將首先處理版本的升級(jí),然后才打開數(shù)據(jù)庫(kù)。
Room做了什么
Room以 Migration 類的形式提供可一個(gè)簡(jiǎn)化SQLite遷移的抽象層。Migration提供了從一個(gè)版本到另一個(gè)版本遷移的時(shí)候應(yīng)該執(zhí)行的操作。Room使用它自己實(shí)現(xiàn)的SQLiteOpenHelper,并在onUpgrade方法中觸發(fā)你定義的遷移步驟。
這里是第一次獲取數(shù)據(jù)庫(kù)時(shí)將發(fā)生的事情:

  1. Room數(shù)據(jù)庫(kù)被創(chuàng)建
  2. SQLiteOpenHelper.onUpgrade 方法被調(diào)用,然后Room觸發(fā)遷移
  3. 數(shù)據(jù)庫(kù)被打開
    如果你增加了數(shù)據(jù)庫(kù)版本但是沒有提供遷移,那么你的app可能會(huì)崩潰,數(shù)據(jù)可能會(huì)丟失,具體清空見下面的討論。
    identity hash字符串在migration內(nèi)部扮演者重要的角色,它用來對(duì)數(shù)據(jù)庫(kù)版本進(jìn)行唯一標(biāo)識(shí)。當(dāng)前版本的identity hash被保存在一個(gè)由Room管理的配置表中。因此如果你在數(shù)據(jù)庫(kù)中看到一個(gè)room_master_table表不要感到奇怪。

三、多版本遷移

要是你的用戶有一個(gè)運(yùn)行版本號(hào)為1的app,想升級(jí)到版本4呢?目前位置我們定義了這些migrations:version 1 到 2, version 2 到 3, version 3 到 4, 所以Room 會(huì)一個(gè)接一個(gè)的觸發(fā)所有 migration。

Room可以處理大于1的版本增量:我們可以一次性定義一個(gè)從1到4的migration,讓遷移的速度更快。

    static final Migration MIGRATION_1_4 = new Migration(1, 4) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            // Create the new table
            database.execSQL(
                    "CREATE TABLE users_new (userid TEXT, username TEXT, last_update INTEGER, PRIMARY KEY(userid))");
            
            // Copy the data
            database.execSQL(
                    "INSERT INTO users_new (userid, username, last_update) SELECT userid, username, last_update FROM users");
    // Remove the old table
            database.execSQL("DROP TABLE users");
    // Change the table name to the correct one
            database.execSQL("ALTER TABLE users_new RENAME TO users");
        }
    };

然后,我們只需把它添加到migration列表中:

    database = Room.databaseBuilder(context.getApplicationContext(),
            UsersDatabase.class, "Sample.db")
            .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4)
            .build();

其它數(shù)據(jù)庫(kù)遷徙到room參考
https://blog.csdn.net/yonghuming_jesse/article/details/98037118

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容