前言
之前做过一个安卓的课程表APP,当时使用time和week来存放课程节数和课程周数,其结构是int-int
类型的一个字符串,因此都每次都需要将字符串分割并转换为int类型来处理,于是在版本更新中我优化了数据结构,将原本的String week
和String time
分别分解成了int wMin;int wMax
以及int tMin; int tMax
;但由于当时没用学习数据库的升级,我直接删除了数据库,不仅造成了原有数据的丢失,还导致软件更新时必须卸载之前安装的软件,现在用到数据库升级可以完美解决相似的问题。
注意!这里均使用Jetpack架构ROOM处理数据库
接上一篇笔记Jetpack学习笔记(一):Room管理数据库
添加字段
1、更新实体对象
在上一篇People对象上加入一个 String字段home
@ColumnInfo(name ="home")
private String home="";
注意:需要添加get/set 否则会报错
2、更新数据库版本
更新之前定义数据库接口PeopleDatabase
的标签,将version
的属性设置比上一个版本高即可
@Database(entities = {People.class},version = 18)
构造新的数据库
INSTANCE= Room.databaseBuilder(context.getApplicationContext(),PeopleDatabase.class,"peo_data") .fallbackToDestructiveMigration()
.build();
.fallbackToDestructiveMigration()
即强制更新,这样会丢失全部数据
3、迁移数据
如果想保留数据需要定义一个数据迁移方法Migration
//参数 从版本 A to B 添加字段
static final Migration MIGRATION_16_17 =new Migration(16,17) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
//添加一列叫
database.execSQL("ALTER TABLE People ADD COLUMN home TEXT");
}
};
同时构造新的数据库时候将fallbackToDestructiveMigration()
这种暴力升级方式修改为addMigrations
即给一个迁移方法,在其中调用刚刚定义的迁移方法
INSTANCE= Room.databaseBuilder(context.getApplicationContext(),PeopleDatabase.class,"peo_data")
.addMigrations(MIGRATION_17_18)
.build();
删除字段
1、更新实体
同上,删除不需要的字段,并删除与之相关的get/set方法
2、迁移数据
由于SQLite没有删除字段方法,因此删除字段需要分为四步,即先创建一个临时数据库=表,将之前的数据按需复制到临时数据表,删除之前的数据表,将临时数据表改名:
2-1、创建临时数据表
database.execSQL("CREATE TABLE people_temp(_id INTEGER PRIMARY KEY NOT NULL , name TEXT , college TEXT )");
2-2、迁移数据
database.execSQL("INSERT INTO people_temp(_id,name,college) " +
"SELECT _id,name,college FROM People");
2-3、删除旧表
database.execSQL("DROP TABLE People");
2-4、改名新表
database.execSQL("ALTER TABLE people_temp RENAME TO People");
3、构造新的数据库
同上,增加数据库的版本,并添加一个迁移方法
INSTANCE= Room.databaseBuilder(context.getApplicationContext(),PeopleDatabase.class,"peo_data")
.addMigrations(MIGRATION_17_18)
.build();
static final Migration MIGRATION_17_18=new Migration(17,18) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
//创建临时表
database.execSQL("CREATE TABLE people_temp(_id INTEGER PRIMARY KEY NOT NULL , name TEXT , college TEXT )");
//迁移复制数据
database.execSQL("INSERT INTO people_temp(_id,name,college) " +
"SELECT _id,name,college FROM People");
//删除旧表
database.execSQL("DROP TABLE People");
//临时表改名
database.execSQL("ALTER TABLE people_temp RENAME TO People");
}
};