Room数据库升级

随着业务的变化,我们的数据库可能也需要做一些调整,例如,我们的数据表可能需要增加一个新字段。这篇文章我们将介绍Room如何升级数据库,升级过程中可能会遇到哪些问题,以及相对于Sqlite和其它ORM,Room有哪些特性值得我们去学习和使用。

Android提供了一个名为Migration的类,来完成Room的升级。

public Migration(int startVersion, int endVersion)

Migration有两个参数,startVersionendVersion。startVersion表示当前版本(手机上安装的版本),endVersion表示将要升级到的版本。如果你的手机中的应用程序数据库的版本为1,那么下方Migration会将你的数据库版本从1升级到2。

static final Migration MIGRATION_1_2 = new Migration(1, 2)
{
    @Override
    public void migrate(@NonNull SupportSQLiteDatabase database)
    {
        //执行升级相关操作
    }
};

以此类推,如果你的数据库需要从2升级到3,则需要写这样一个Migration。

private static Migration MIGRATION_2_3 = new Migration(2, 3)
{
    @Override
    public void migrate(@NonNull SupportSQLiteDatabase database)
    {
        //执行升级相关操作
    }
};

如果用户手机上安装的应用程序数据库版本为1,而当前要安装的应用程序数据库版本为3,这种情况该怎么办呢?这种情况下,Room会先判断当前有没有从1->3的Migration升级方案,如果有,就直接执行从1->3的升级方案,如果没有,那么Room会按照顺序先后执行Migration(1, 2)->Migration(2, 3)以完成升级。

写好Migration之后,我们还需要通过addMigrations()方法,将升级方案添加到Room。

Room.databaseBuilder(context.getApplicationContext(), MyDatabase.class, DATABASE_NAME)
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_1_3)
    .build();

异常处理

假设此时我们升级系统版本为4,却没有为此写相应的Migration,则会出现一个IllegalStateException异常。

Caused by: java.lang.IllegalStateException: A migration from 3 to 4 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.
        at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:117)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:124)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:400)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getReadableSupportDatabase(FrameworkSQLiteOpenHelper.java:103)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getReadableDatabase(FrameworkSQLiteOpenHelper.java:58)

这是因为Room在升级过程中没有匹配到相应的Migration。为了防止出现升级失败导致应用程序Crash的情况,我们可以在创建数据库时加入fallbackToDestructiveMigration()方法。该方法能够在出现升级异常时,重新创建数据库表。虽然应用程序不会Crash,但由于数据表被重新创建,所有的数据也将会丢失。

Room.databaseBuilder(context.getApplicationContext(), MyDatabase.class, DATABASE_NAME)
    .fallbackToDestructiveMigration()
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_1_3)
    .build();

如何修改Room数据库的版本号呢?直接通过@Database标签中的version属性进行修改就可以了。

@Database(entities = {Student.class}, version = 1)

Schema文件

在没有Room之前,如果想要验证数据库的修改是否符合我们的预期,我们可能需要找到这个数据库文件,然后使用第三方Sqlite查看工具,对其进行查看和验证。另外,我们希望能够查看到数据库的历次升级情况,似乎也只能通过代码版本控制工具来查看源代码。这无疑是非常耗时耗力的。为此,Room提供了一项功能,在每次数据库的升级过程中,它都会为你导出一个Schema文件,这是一个json文件,里面包含了数据库的所有基本信息。有了这些文件,开发者们就能知道数据库的历史变更情况,极大地方便了开发者们排查问题。Schema文件是默认导出的,你只需要指定它导出的位置即可。

appbuild.gradle文件中指定Schema文件的导出位置。

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]//指定数据库schema导出的位置
            }
        }
    }
}

这样,当你的数据库生成后,你便可以在项目的根目录下看见这些文件。数字代表着数据库的版本号。

这篇文章我们介绍了如何使用Migration升级我们的数据库。除此之外,我们还指出了升级过程中可能会出现的异常。Schema文件是Room提供的非常实用的一个特性,它的作用有点类似一个针对数据库的Git仓库,有了它,便能知道数据库的历史变更情况。在开发过程中,Schema文件还可以帮助我们判断对数据库的修改是否成功。最后,我们还介绍了销毁与重建策略,当我们遇到一些复杂情况的时候,可以考虑利用这种策略升级我们的数据库。  

转自:Android之Room数据库升级_凯凯kai的博客-CSDN博客_please provide the necessary migration path via ro

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"编写: 非常6+2 "日期:2013-7-31 " "审核: "日期: " "批准: "日期: " "受控状态: "是 " "发布版次:5.0 "日期:2013-7-31 " "编号: " 变更记录 "日期 "版本 "变更说明 "作者 " "2013-7-17 "1.0 "初始文档 "匿名 " "2013-7-25 "2.0 "升级文档 "匿名 " "2013-7-29 "3.0 "升级文档 "匿名 " "2013-7-30 "4.0 "升级文档 "匿名 " "2013-7-31 "5.0 "最终文档 "匿名 " " " " " " 签字确认 "职务 "姓名 "签字 "日期 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " 目 录 1 引言 4 1.1 预期的读者 4 1.2 数据库说明 4 1.3 目的和作用 4 2 数据库设计 4 2.1 抽象数据对象 4 2.1.1 系统主要业务分析 4 2.1.2 需求分析参考 5 2.2 系统物理结构设计 5 2.3 数据库逻辑设计 5 2.3.1 数据库设计命名规范 6 2.3.2 数据库表名汇总 7 2.3.3 数据库表结构设计 7 2.4 存储过程设计 12 2.5 触发器设计 12 2.6 Job设计 12 3 数据字典设计 13 引言 1 预期的读者 主要为本公司以及承包方的阅读者,如设计人员、开发人员等。有时可以包括客户方 的阅读者,如:业务人员、系统管理人员等。 2 数据库说明 会议管理系统采用的时当前流行的企业级数据库oracle,使用的版本是9i。设计的数 据库全局数据库名为icss,开发用的表空间名是test,操作的用户名为test,密码为te st。 3 目的和作用 将业务分析,系统设计中对信息的描述进一步分析并加以总计,抽象出数据集合(数 据库表)。对数据集合做进一步分析,确定集合之间的关系并最终形成数据库物理模型 ,以便开发人员建立物理数据库数据库设计 1 抽象数据对象 1 系统主要业务分析 根据物流系统的业务流程描述,我们大致可以从中抽象出几个数据集合,如: 普通用户、会议申请、会议室管理、设备管理、会议管理 按照业务及系统功能简单总结数据对象: 用户 会议申请信息 会议审批 会议设备 2 需求分析参考 根据系统需求分析内容进一步确定数据对象。由于系统需求分析中考虑到会议室和会 议设备间有一定的区别和联系,即会议室一般包含固定设备和移动设备,两者之间并不 是并列关系而是所属关系,所以将会议室默认含有固定设备,这样,设备只有移动设备 分开,并提出单独的信息维护功能,数据库对象也进一步细化将会议设备分成,会议室 和相关设备。会议申请和会议审批操作的都是相同对象所以将两个数据对象进行合并, 其他数据对象没有变化。 总结数据对象: 用户信息 会议信息 会议室 会议设备 2 数据库结构设计 根据系统的分布式部署设计,数据库将部署到一部独立的计算机中。根据前期的分析 ,系统将有大量的数据存放入数据库。预留数据库空间500m,日增长约3m,日志空间1G ,日增长5m。 数据库位置:*oracle9ipath*/n2ms/db/ 日志位置:*oracle9ipath*/n2ms/log/ 3 数据库设计命名规范 1,表名命名规则 本数据库使用的表名一律采用有意义的小写英文字符命名,考虑将来编码方便,表名 不 使用'-'连接相关 2,表项命名规则 本数据库各个表的每个字段,依照表名命名规则,全部使用有意义的小写英文字符 命名,字段名不适用'-'连接相关字符,方便编码书写。 4 数据库逻辑设计 表设计中应注意的问题: 1.对于字符类型的字段,要仔细确认字段的可能长度。在oracle数据库设计中,一 般来说,对于定长的字符数据字段,取字符类型(char),对于不定长的,取变长字符类 型(varchar)。 2.对于以分类形式出现的字段,建议不使用字符类型,而使用数字类型。如:货物 是否配送为是或(和)否;如果用字符类型,则将这些字符串需要入库;如果使用数字 类型分别用1、0代表高职、中职、低职,则入库的是数字信息,从程序编写的角度考虑 ,后者更好维护一些,主要体现在如果是多语言版本时,我们不需要在程序中将这些字 符串信息进行判断处理。 1 数据库表名汇总 表2-1 数据库表 "数据库表名 "中文名 "文字说明 " "meet_app "会议申请信息 "保存所开会议的基本信息 " "meet_room "会议室 "保存会议室情况的相关信息" "facilty_meet "设备信息 "保存会议设备的相关信息 " "Equipment_stype "设备类型 "保存相关设备类型信息 " "users_in

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值