基于上一篇的demo,记录一下升级数据库的笔记。
在表中添加一列性别
在database中添加语句
private static final Migration MG_1_TO_2 = new Migration(1,2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE student ADD COLUMN sex INTEGER NOT NULL DEFAULT 1");
}
};
生成db时设置
instance = Room.databaseBuilder(context.getApplicationContext(),
MyDataBese.class,
mDBName)
.addMigrations(MG_1_TO_2)
.build();
DataBase注释中设置升级的版本和生成数据库升级json代码文件
![](https://img.haomeiwen.com/i10002669/48fd407b1e2eb98b.png)
当然gradle中要配置schema的生成路劲
defaultConfig {
applicationId "com.example.myapplication"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
dataBinding{
enabled = true
}
//指定room.schemaLocation生成的文件路径
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
Student实例类添加sex字段
@ColumnInfo(name = "sex", typeAffinity = ColumnInfo.INTEGER)
public int sex;
//room 需要的构造方法
public Student(int id, String name, int age,int sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
room_item_layout.xml稍微修改一下布局,展示性别
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="student"
type="com.example.myapplication.jetpack.room.Student" />
<import type="com.example.myapplication.jetpack.room.StringTools"/>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="id"
android:text="@{String.valueOf(student.id)}"
android:textSize="18sp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:textColor="@android:color/black"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="name"
android:text="@{StringTools.append(student.name,String.valueOf(student.sex))}"
android:textSize="18sp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:textColor="@android:color/black"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="age"
android:text="@{String.valueOf(student.age)}"
android:textSize="18sp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:textColor="@android:color/black"/>
</RelativeLayout>
</layout>
StringTools
public class StringTools {
public static String append(String name,String sex){
return "名字:"+name+" 性别:"+getSex(sex);
}
private static String getSex(String sex) {
if(TextUtils.equals(sex,"1")){
return "男";
}else if(TextUtils.equals(sex,"0")){
return "女";
}else{
return "男";
}
}
}
Room的升级,如果一个1版本直接装了一个3版本的话,中间间隔的2版本会被Room依次执行,所以不用担心执行不到。
数据库升级失败处理
fallbackToDestructiveMigration方法设置数据库升级异常时,删除原本数据,并新建能用的原始结构的表。
instance = Room.databaseBuilder(context.getApplicationContext(),
MyDataBese.class,
mDBName)
.addMigrations(MG_1_TO_2)
.fallbackToDestructiveMigration()
.build();
数据库的销毁和重建
如果我们要对表里的字段进行类型的修改,那么我们最好是先备份数据到新表再销毁原来的表。接下来实操一下。比如吧刚刚新加的sex字段改为TEXT类型
先编写2到3的sql逻辑
private static final Migration MG_2_TO_3 = new Migration(2,3) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
//设置新的零时表
database.execSQL("CREATE TABLE temp_student (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"+
"name TEXT,"+
"age INTEGER NOT NULL,"+
"sex TEXT DEFAULT 'M'"+
")");
//复制老数据到零时表
database.execSQL("INSERT INTO temp_student(name,age,sex)" +
"SELECT name,age,sex FROM student");
//删除旧的表
database.execSQL("DROP TABLE student");
//重命名零时表
database.execSQL("ALTER TABLE temp_student RENAME TO student");
}
};
添加到设置
instance = Room.databaseBuilder(context.getApplicationContext(),
MyDataBese.class,
mDBName)
.addMigrations(MG_1_TO_2,MG_2_TO_3)
.fallbackToDestructiveMigration()
.build();
最后数据库升级
@Database(entities = {Student.class}, version = 3,exportSchema = true)
修改实例类
@ColumnInfo(name = "sex", typeAffinity = ColumnInfo.TEXT)
public String sex;
修改工具类
public class StringTools {
public static String append(String name,String sex){
return "名字:"+name+" 性别:"+getSex(sex);
}
private static String getSex(String sex) {
if(TextUtils.equals(sex,"M")){
return "男";
}else if(TextUtils.equals(sex,"W")){
return "女";
}else{
return "男";
}
}
}
OK,这样我们就完成了属性换类型的操作了,挺麻烦的。
预填充数据
createFromAsset,可以在用户没有数据时将已有数据库数据填入到我们的数据库文件中。但是要保证我们的实例类和已有数据库数据库结构相同。
instance = Room.databaseBuilder(context.getApplicationContext(),
MyDataBese.class,
mDBName)
.addMigrations(MG_1_TO_2,MG_2_TO_3)
.fallbackToDestructiveMigration()
.createFromAsset("city.db")
.build();
网友评论