正常我们在开发中经常会遇到sqlite数据库升级的问题,比如增加字段/删除字段/表结构重构等等,随着apk版本的升高,不同版本可能需要对数据库进行修改,但是要求是数据库升级不能影响用户的已存数据,所以今天就来看看数据库升级流程是怎样的。
目录
-
SQLiteDatabase源码调用流程
- 首先我们需要继承 SQLiteOpenHelper, 下面是 SQLiteOpenHelper 的源码注释:
SQLiteOpenHelper is a helper class to manage database creation and version management.
然后会提示让我们去重写他的三个方法:
public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
@Nullable CursorFactory factory, int version) {
this(context, name, factory, version, null);
// 传入我们的数据库名称 和 版本号version
}
@Override
public void onCreate(SQLiteDatabase db) {
// 创建表
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 版本升级
}
2. 分析以下上述三个方法调用的时机,何时会被调用。
- 构造方法--首先我们创建数据库操作类的时候先走构造方法,通过构造方法会把数据库名称和版本号 传 SQLiteOpenHelper
当然这只是创建了,数据库操作类,数据库还没有创建。 - onCreate() 方法是创建表的,只有第一次才会走这个方法,首次创建数据库的时候才会走,之后就不会走了。
- onUpgrade()数据库升级,这个方法只有构造方法中传的版本号发生了升级才会走,所以我们升级的逻辑就在这里处理。
以上只是常用的方法,还有数据库降级等等方法按需重写。
3. 方法调用的源码流程图
根据这个流程图配合我们的源码更容易理解 sqlite 整个创建流程,这就是整个数据库版本检测和获得db的过程。对整个流程熟悉了之后,接下来我们就好理解数据库升级。
-
数据库自动升级流程
对于升级我们就举一个例子,从db version 1 升级到db version 2的过程:
假如我们的表结构是这样的
* version = 1;
* auto integer REAL REAL
* _id color loc_x loc_y
* version = 2; 添加了一个 字段 time
* auto integer REAL REAL REAL
* _id color loc_x loc_y time
通过分析源码我们知道数据库升级是在 onUpgrade() 方法中的,接下来分析升级流程:
- 创建临时缓存表 用于缓存老表里面的数据
- 查询老表中的数据并且把数据插入到缓存的表中去
- 删除老表,创建新的表结构
- 把缓存表数据重新插入到新的表结构中去
- 调用查询,插入检测是否升级成功
- 升级结束
整个流程就这些,接下来把升级的代码贴上,特别要注意的是升级的流程要放到子线程中去!
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//创建临时缓存表 用于缓存老表里面的数据
String createTable = "CREATE TABLE " + snapCachedTableName
+ " (" + CustomColorEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ CustomColorEntry.COLUMN_NAME_COLOR + " INTEGER,"
+ CustomColorEntry.COLUMN_NAME_LOCX + " REAL,"
+ CustomColorEntry.COLUMN_NAME_LOCY + " REAL)";
db.execSQL(createTable);
//查询所有的老表数据
List<CustomColor> colors = getCustomColors(CustomColorEntry.TABLE_NAME,db);
//把数据插入到缓存的表中去
for (CustomColor color : colors){
insertCustomColor(color, snapCachedTableName,db);
}
db.execSQL("drop table " + CustomColorEntry.TABLE_NAME);
//创建新的表结构
String createNewTable = "CREATE TABLE " + CustomColorEntry.TABLE_NAME
+ " (" + CustomColorEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ CustomColorEntry.COLUMN_NAME_COLOR + " INTEGER,"
+ CustomColorEntry.COLUMN_NAME_LOCX + " REAL,"
+ CustomColorEntry.COLUMN_NAME_LOCY + " REAL,"
+ CustomColorEntry.COLUMN_NAME_TIME + " REAL)";
db.execSQL(createNewTable);
//查询所有的缓存表中的数据
List<CustomColor> cachedColors = getCustomColors(snapCachedTableName,db);
//把数据插入到新的表中去
for (CustomColor color : cachedColors){
insertCustomColor(color, CustomColorEntry.TABLE_NAME,db);
}
db.execSQL("drop table " + snapCachedTableName);
}
传送门github:https://github.com/WangRain1/DbUpgradeDemo 大家给点支持,笑嘻嘻