1. 版本号的位置:

@Database(entities = {LogEntity.class}, version = 1, exportSchema = false)

就是这里的 Version

以下引用自掘金:Room踩坑:理解Room的正确升库 - 掘金

感谢 咸鱼正翻身 ,写的非常清楚,不需要再改动,因此直接引用

这篇文章翻译于Google的官方博客(自备科学上网),是我踩坑后搜到的,贴出来希望大家避免掉坑里吧~

一、场景1:vesion不变 - crash

此时运行app,crash欢迎你:

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(entities = {User.class}, version = 2)
public abstract class UsersDatabase extends RoomDatabase

我们会遇到另一个问题:

二、场景2:增加vesion,但不提供Migration - crash

当我们把version从1改到了2。此时兴高采烈的从老版本升级上来后...crash欢迎你:

java.lang.IllegalStateException: A migration from 1 to 2 is necessary. Please provide a Migration in the builder or call fallbackToDestructiveMigration in the builder in which case Room will re-create all of the tables.

三、场景3:增加vesion,使用fallback migration - 数据被清除

不提供自定义Migration,又不想引发crash,那么可以试试这个:

database = Room.databaseBuilder(context.getApplicationContext(),UsersDatabase.class, "Sample.db").fallbackToDestructiveMigration().build();

不过,用之前请好好理解它的意思:

Room启动时将检测version是否发生增加,如果有,那么将找到Migration去执行特定的操作。如果没有因为fallbackToDestructiveMigration()。将会删除数据库并重建...

此时的确不会crash,但所有数据丢失。

四、场景4:vesion增加,提供Migration - 数据正常

如果version发生变化,即使表结构没有变化仍然需要提供Migration,那么此时应该怎么做呢?

@Database(entities = {User.class}, version = 2)
public abstract class UsersDatabase extends RoomDatabase {
// …
static final Migration MIGRATION_1_2 = new Migration(1, 2) {@Overridepublic void migrate(SupportSQLiteDatabase database) {// 因为没有变化,所以是一个空实现}
};
// …
database =  Room.databaseBuilder(context.getApplicationContext(),UsersDatabase.class, "Sample.db").addMigrations(MIGRATION_1_2).build();

五、场景5:改表结构

如果我们此时又想升级数据,并且这次需要更改表结构:给user表加一个last_update的字段。那么此时我们改怎么办?

1、先增加version

@Database(entities = {User.class}, version = 3)
public abstract class UsersDatabase extends RoomDatabase

2、提供Migration

static final Migration MIGRATION_2_3 = new Migration(2, 3) {@Overridepublic void migrate(SupportSQLiteDatabase database) {database.execSQL("ALTER TABLE users "+ " ADD COLUMN last_update INTEGER");}
};

PS:很多老铁,看到这可能觉得头疼。还得写这么多sql。其实有一个取巧的方式,当在User.class增加完字段,编译后全局搜索3.json。你会发现sql语句已经被生成出来了。

3、修改Room.databaseBuilder

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

大功告成,基本的升库的用法我们已经了解完了。但是这也只是基本的用法,我相信有追求的小伙伴,可能需要来点更“刺激”的才行~

六、复杂的Migration

延续我们上边的表结构,此时我们想改表:把刚才增加的Int型的last_update改成String。

我猜有经验的老司机,已经猜到需要怎么做了:

  • 创建一个新的临时表,
  • 将数据从users表复制到临时表,
  • 删了users表
  • 将临时表重命名为users

那么针对此次更新,我们需要提供这样的Migration:

static final Migration MIGRATION_3_4 = new Migration(3, 4) {@Overridepublic void migrate(SupportSQLiteDatabase database) {// 创建临时表database.execSQL("CREATE TABLE users_new (userid TEXT, username TEXT, last_update INTEGER, PRIMARY KEY(userid))");// 拷贝数据database.execSQL("INSERT INTO users_new (userid, username, last_update) SELECT userid, username, last_update FROM users");// 删除老的表database.execSQL("DROP TABLE users");// 改名database.execSQL("ALTER TABLE users_new RENAME TO users");}
};

此时我们用version3版本的app升级到version4的app的确没有问题,很爽。不过我们多想一个问题:如果从version1版本的用户直接升到version4版本会怎么样?

**其实不会有问题!**Room会对这种用户一直执行1-2的Migration,2-3的Migration已经3-4的Migration。这很方便,不过如果你追求极致的性能和体验,你可以提供一个1-4的Migration,比如这样:

static final Migration MIGRATION_1_4 = new Migration(1, 4) { // 除了这一行,其他的和上边一样@Overridepublic void migrate(SupportSQLiteDatabase database) {// 创建临时表database.execSQL("CREATE TABLE users_new (userid TEXT, username TEXT, last_update INTEGER, PRIMARY KEY(userid))");// 拷贝数据database.execSQL("INSERT INTO users_new (userid, username, last_update) SELECT userid, username, last_update FROM users");// 删除老的表database.execSQL("DROP TABLE users");// 改名database.execSQL("ALTER TABLE users_new RENAME TO users");}
};

然后把Migration加进来就ok了。

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

以下引用自:

Android room 升级问题 - 简书

增加了一个字符串类型

database.execSQL("ALTER TABLE my_tab"+ " ADD COLUMN configString TEXT");

增加int类型字段

database.execSQL("ALTER TABLE CallLog "+ " ADD COLUMN e164 INTEGER");

如果你的表,保存的数据是List<String>,其实他保存就是string来,所以,增加list的时候,是增加string

database.execSQL("ALTER TABLE CallLog "+ " ADD COLUMN list TEXT");

当你的表更换了索引你需要做的就是:
删除旧索引

//tab 表明,索引字段phones
database.execSQL("DROP INDEX IF EXISTS `index_tab_phones`");

增加新的索引

database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS index_tab_default_number ON tab(default_number)");

Android Room 数据库升级相关推荐

  1. Android Room数据库升级

    一.数据库升级 数据库升级在每一个版本上新的时候会经常遇到,一般是表字段进行了修改.一般新增一些字段的情况比较多.以下四步是完成数据库升级的基本步骤. 二.代码实现 1.添加Entity字段 原Ent ...

  2. Android SQLite数据库升级的问题

    SQLite是Android内置的一个很小的关系型数据库.SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类.我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定 ...

  3. Android GreenDao3数据库升级,数据迁移

    GreenDao3,当我们进行数据库版本升级的时候,会默认删除删除所有的表,然后重新创建 WARNING已经提示我们了,如果我们需求是在升级数据库之后保存当前的所有数据,则需要对onUpgrade( ...

  4. Android 数据库升级解决方案

    请考虑如下情况: 在数据库升级时,不同版本的数据库,他们定义的表结构完全可能是不一样的,比如V1.0的表A有10个column,而在V1.1的表A有12个colum,在升级时,表A增加了两列,此时我们 ...

  5. Android数据库升级实例

    第一部分 Andoird的SQLiteOpenHelper类中有一个onUpgrade方法.帮助文档中只是说当数据库升级时该方法被触发.经过实践,解决了我一连串的疑问: 1. 帮助文档里说的" ...

  6. Android ORM 框架:GreenDao 数据库升级

    本文作者:Speedy CSDN 专栏:blog.csdn.net/speedystone 掘金专栏:juejin.im/user/57e082- 前言 在 Android ORM 框架:GreenD ...

  7. Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点

    以下内容可以作为面试官在面试的时候的问题,感觉比较好,是比较常用的知识点,可以用来考察基础是否扎实. 也可以程序猿学习.开发中的注意点.因为稍微不注意,就有可能导致数据库不能用. DBAdapter. ...

  8. Android SQLite数据库版本升级(分逐级升级和跨版本升级)

    参考:Android Sqlite数据库跨版本升级 保存之前数据 本文说的数据库升级是基于Android原生APISQLiteOpenHelper实现的逻辑,不涉及第三方库.其实如果使用官方推荐的Ro ...

  9. 18.移动架构数据库升级解决方案

    今天的数据库升级将通过这个脚本文件完成,我们假设目前版本迭代中,已经上线了V001 V002版本,近期将要上线V003.首先先理清三个版本的数据库情况,三个版本中都涉及一个个数据库文件(暂不考虑分库的 ...

最新文章

  1. 20172328《程序设计与数据结构》实验二:树
  2. 关于js中window.location.href、location.href 等如何跳转
  3. Linux设置 cockpit 自动开机启动
  4. windows下consul安装启动
  5. jquery scrollTop及其应用例子
  6. 利用unittest+ddt进行接口测试(二):使用yaml文件管理测试数据
  7. 计算机组成与体系结构重点(四川大学软件学院)
  8. 操作 神通数据库_神通数据库命令行
  9. PointNet解读
  10. 黑盒测试中的因果图约束条件解释
  11. 每日一题——有效的数独
  12. leetcode:359. 日志速率限制器
  13. 分享、活动、地推、广告:openinstall全渠道多场景解决方案
  14. 汽车多媒体主机接口EMC设计
  15. ccna 服务器输入域名显示不出,思科为服务器设置域名
  16. java 三个字母组合_每天AC系列(三):电话号码的字母组合
  17. 区块链知识系列 - App 与 DApp 的区别
  18. ctfshow 做题 萌新 模块(3)
  19. tunel凋亡试剂盒说明书_急求!!罗氏TUNEL试剂盒( In Situ Cell Death Detection Kit, TMR red )中文说明书或者操作步骤,急急急!!谢谢啦!...
  20. 投资理财-朋友榕的经历

热门文章

  1. vue路由跳转的几种方式
  2. 费米估算 “ 我为什么没有女朋友?”
  3. 移动硬盘数据错误循环冗余检查要如何寻回文件
  4. 用 卡莱特A35播放盒子 在局域网内更新单行文本
  5. 5种暗黑系艺术效果lr预设
  6. 【转】华为PCB布线规范
  7. 湛江计算机学校中专,湛江中专院校名单 湛江有哪些中专学校
  8. initRD的启动流程分析
  9. 【计算机组成原理】溢出
  10. 『王霸之路』从0.1到2.0一文看尽TensorFlow奋斗史