Android Room 数据库升级
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 数据库升级相关推荐
- Android Room数据库升级
一.数据库升级 数据库升级在每一个版本上新的时候会经常遇到,一般是表字段进行了修改.一般新增一些字段的情况比较多.以下四步是完成数据库升级的基本步骤. 二.代码实现 1.添加Entity字段 原Ent ...
- Android SQLite数据库升级的问题
SQLite是Android内置的一个很小的关系型数据库.SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类.我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定 ...
- Android GreenDao3数据库升级,数据迁移
GreenDao3,当我们进行数据库版本升级的时候,会默认删除删除所有的表,然后重新创建 WARNING已经提示我们了,如果我们需求是在升级数据库之后保存当前的所有数据,则需要对onUpgrade( ...
- Android 数据库升级解决方案
请考虑如下情况: 在数据库升级时,不同版本的数据库,他们定义的表结构完全可能是不一样的,比如V1.0的表A有10个column,而在V1.1的表A有12个colum,在升级时,表A增加了两列,此时我们 ...
- Android数据库升级实例
第一部分 Andoird的SQLiteOpenHelper类中有一个onUpgrade方法.帮助文档中只是说当数据库升级时该方法被触发.经过实践,解决了我一连串的疑问: 1. 帮助文档里说的" ...
- Android ORM 框架:GreenDao 数据库升级
本文作者:Speedy CSDN 专栏:blog.csdn.net/speedystone 掘金专栏:juejin.im/user/57e082- 前言 在 Android ORM 框架:GreenD ...
- Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点
以下内容可以作为面试官在面试的时候的问题,感觉比较好,是比较常用的知识点,可以用来考察基础是否扎实. 也可以程序猿学习.开发中的注意点.因为稍微不注意,就有可能导致数据库不能用. DBAdapter. ...
- Android SQLite数据库版本升级(分逐级升级和跨版本升级)
参考:Android Sqlite数据库跨版本升级 保存之前数据 本文说的数据库升级是基于Android原生APISQLiteOpenHelper实现的逻辑,不涉及第三方库.其实如果使用官方推荐的Ro ...
- 18.移动架构数据库升级解决方案
今天的数据库升级将通过这个脚本文件完成,我们假设目前版本迭代中,已经上线了V001 V002版本,近期将要上线V003.首先先理清三个版本的数据库情况,三个版本中都涉及一个个数据库文件(暂不考虑分库的 ...
最新文章
- 20172328《程序设计与数据结构》实验二:树
- 关于js中window.location.href、location.href 等如何跳转
- Linux设置 cockpit 自动开机启动
- windows下consul安装启动
- jquery scrollTop及其应用例子
- 利用unittest+ddt进行接口测试(二):使用yaml文件管理测试数据
- 计算机组成与体系结构重点(四川大学软件学院)
- 操作 神通数据库_神通数据库命令行
- PointNet解读
- 黑盒测试中的因果图约束条件解释
- 每日一题——有效的数独
- leetcode:359. 日志速率限制器
- 分享、活动、地推、广告:openinstall全渠道多场景解决方案
- 汽车多媒体主机接口EMC设计
- ccna 服务器输入域名显示不出,思科为服务器设置域名
- java 三个字母组合_每天AC系列(三):电话号码的字母组合
- 区块链知识系列 - App 与 DApp 的区别
- ctfshow 做题 萌新 模块(3)
- tunel凋亡试剂盒说明书_急求!!罗氏TUNEL试剂盒( In Situ Cell Death Detection Kit, TMR red )中文说明书或者操作步骤,急急急!!谢谢啦!...
- 投资理财-朋友榕的经历