Android Room 中的數(shù)據(jù)庫自動遷移、生成臨時表功能

在 Android 開發(fā)中,數(shù)據(jù)庫的升級往往需要進行手動遷移,這是一件比較繁瑣的事情。而在 Android Room 中,提供了自動遷移的功能,大大減輕了開發(fā)者的負擔。
當我們對數(shù)據(jù)庫的表結(jié)構(gòu)進行了修改,例如添加了新的列和索引,我們需要升級數(shù)據(jù)庫版本以便應(yīng)用程序能夠正確地處理新的數(shù)據(jù)。在 Android Room 中,我們可以使用 @Database 注解中的 version 屬性來指定版本號,然后使用 @Entity 注解中的 indicescolumns 屬性來添加索引和列。

為了讓 Room 能夠自動遷移數(shù)據(jù)庫,我們需要在 @Database 注解中添加 autoMigrations 屬性,并提供一個數(shù)組,數(shù)組中的每個元素表示一個自動遷移操作。每個自動遷移操作都包含 fromVersiontoVersion 兩個屬性,分別表示起始版本和目標版本。在進行自動遷移時,Room 會自動根據(jù)起始版本和目標版本之間的差異來執(zhí)行相應(yīng)的操作。

一、自動升級

官方文檔地址:

https://developer.android.google.cn/training/data-storage/room/migrating-db-versions?hl=zh-cn

1.引入room的依賴

def room_version = "2.5.0-alpha01"http://2.2.5
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

2.設(shè)置room數(shù)據(jù)庫生成表的sql語句,這一步非常重要

defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += [
                        "room.schemaLocation":"$projectDir/schemas".toString(),
                        "room.incremental":"true",
                        "room.expandProjection":"true"]
            }
        }
    }

3.基本的配置好了以后我們就可以正常的來增加注解來配置數(shù)據(jù)的庫的自動升級了

@Database(entities = {UserBean.class, SchoolsBean.class},
        exportSchema = true,
        version = 8,
        autoMigrations = [
            AutoMigration (from = 1, to = 2)
                ]
)
public abstract class MyDatabase extends RoomDatabase {}

4.如果需要在表里新增一個字段如test字段,只需要增加一個@ColumnInfo注解,并為其賦一個默認值

 @ColumnInfo(defaultValue = "0")

配置完成后,我們的項目中schemas 目錄會存在多個json文件,這個是本地數(shù)據(jù)庫各個版本的sql語句,請注意,這些json文件需要保存不能刪除,否則下次升級會找不到上個數(shù)據(jù)庫的文件,導(dǎo)致自動升級失敗

手動升級數(shù)據(jù)庫
val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

.addMigrations(MIGRATION_1_2)//可以添加多個參數(shù),以便從1->2,2->3,1->3

銷毀表創(chuàng)建臨時表重建

  • 創(chuàng)建一張符合表結(jié)構(gòu)要求的臨時表,
  • 將數(shù)據(jù)從舊表復(fù)制到臨時表,
  • 刪除舊表,
  • 臨時表重命名回原來的表名

異常處理

為了防止升級過程中失敗導(dǎo)致應(yīng)用程序崩潰的情況,可以在創(chuàng)建數(shù)據(jù)庫時加入fallbackToDestructiveMigration()方法。該方法能在數(shù)據(jù)庫升級異常時,重建數(shù)據(jù)庫而不崩潰,但是表中的數(shù)據(jù)會丟失

val MIGRATION_2_3: Migration = object : Migration(2, 3) {
            override fun migrate(database: SupportSQLiteDatabase) {
                //創(chuàng)建臨時表
                database.execSQL(
                    "CREATE TABLE tem_user_info (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_name` TEXT, `last_name` TEXT, `sex` INTEGER DEFAULT 0)"
                )
                //將數(shù)據(jù)導(dǎo)入臨時表
                database.execSQL("INSERT INTO tem_user_info (uid,first_name,last_name,sex) SELECT uid,first_name,last_name,sex FROM user_info")
                //刪除原表
                database.execSQL("DROP TABLE user_info")
                //臨時表改成原表的名字
                database.execSQL("ALTER TABLE tem_user_info RENAME TO user_info")
            }
        }

二、自動遷移

Room 的自動遷移無法檢測到數(shù)據(jù)庫上執(zhí)行的所有可能的變化,因此有時候它們需要一些幫助。舉一個常見的例子,Room 沒辦法檢測到一個數(shù)據(jù)庫表或列是否被重命名或者被刪除。在這種情況下,Room 會拋出一個編譯錯誤,并要求您實現(xiàn) AutoMigrationSpec。此類允許您指定做出更改的類型,實現(xiàn)一個 AutoMigrationSpec 并使用以下一項或多項來注解:

  • @DeleteTable(tableName)
  • @RenameTable(fromTableName, toTableName)
  • @DeleteColumn(tableName, columnName)
  • @RenameColumn(tableName, fromColumnName, toColumnName)

假設(shè)我們將 User的數(shù)據(jù)庫表重命名為 Users。Room 無法檢測到我們是新建了這個表并刪除了 User 表,還是重命名了它以及要保留所有的值。

@Database(version = 2,
        entities = [GoodDoggos.class],
        autoMigrations = [AutoMigration(from = 1,
                to = 2,
                spec = MyDatabase.UsersAutoMigration::class)])
abstract class MyDatabase: RoomDatabase {
    @RenameTable(fromTableName = "User", toTableName = "Users")
    class UsersAutoMigration: AutoMigrationSpec{}
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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