我们在开发 Android App 过程中难免会用到数据库,而数据库版本号通常会碰到升级或降级(降级应该比较少)的情况。那我们该如何去升级或者降级我们的数据库的版本号呢?
我先描述我碰到的一个数据库升级的情况。
一开始数据库的版本号是 1 ,有一天需求变动了,需要增加一个字段,毫无疑问,数据库需要升级,我的 SQLiteOpenHelper 大概是这么写的。
public MySqliteHelper extends SQLiteOpenHelper {
...
public void onUpgrade(int oldVersion , int newVersion) {
if( oldVersion == 1 && newVersion == 2 ) {
// 添加一个字段
}
}
}
我们接着继续开发,过了一段时间,我们的需求又变了,数据库的版本号需要升级到 3 ,这个时候我们会碰到什么情况呢?
一、版本号由 1 直接升到 3
二、版本号由 2 直接升到 3
其实这个也好处理,在 SQLiteOpenHelper 里面多判断一下。
public MySqliteHelper extends SQLiteOpenHelper {
...
public void onUpgrade(int oldVersion , int newVersion) {
if( oldVersion == 1 && newVersion == 3 ) {
// 由版本 1 升到版本 3
}
if( oldVersion == 2 && newVersion == 3 ) {
// 由版本 2 升到版本 3
}
}
}
貌似也没有什么问题,可仔细想一想,如果我的数据库版本号需要升级到 10 了,我们会碰到 1 -> 10 , 2 -> 10 , 3 -> 10 , 4 -> 10 , 5 -> 10 , 6 -> 10 , 7 -> 10 , 8 -> 10 , 9 -> 10 共 9 种升级情况 , 那不就是要写 9 个判断语句?
还有就是,以前写的版本号由 1 升级到 9 的代码有可能没用了,需要从新写。
还有一个更严重的问题就是数据库版本号为 1 的表结构和数据库版本号为10 的表结构应该发生了比较大的变化,1 -> 10 这个过程可能经历了好几个开发者,新的开发者不一定能快速准确的把 1 -> 10 升级代码写出来。
那,我们该怎么办呢?就拿刚刚举得例子来说,我大概会这么做。
public MySqliteHelper extends SQLiteOpenHelper {
...
public void onUpgrade(int oldVersion , int newVersion) {
int fixedVersion = oldVersion
if( fixedVersion == 1 ) {
// 由版本 1 升到版本 2
fixedVersion = 2;
}
if( fixedVersion == 2 ) {
// 由版本 2 升到版本 3
fixedVersion = 3;
}
if( fixedVersion == 3 ) {
// 由版本 3 升到版本 4
fixedVersion = 4;
}
if( fixedVersion == 4 ) {
// 由版本 4 升到版本 5
fixedVersion = 5;
}
if( fixedVersion == 5 ) {
// 由版本 5 升到版本 6
fixedVersion = 6;
}
if( fixedVersion == 6 ) {
// 由版本 6 升到版本 7
fixedVersion = 7;
}
if( fixedVersion == 7 ) {
// 由版本 7 升到版本 8
fixedVersion = 8;
}
if( fixedVersion == 8 ) {
// 由版本 8 升到版本 9
fixedVersion = 9;
}
if( fixedVersion == 9 ) {
// 由版本 9 升到版本 10
fixedVersion = 10;
}
if( fixedVersion == newVersion ) {
// 升级成功
} else {
// 升级失败
}
}
}
为什么这么做呢?其实,这个做法的原理是
1 -> 2 , 2 -> 3 , 3 -> 4 , 4 -> 5 , 5 -> 6 , 6 -> 7 , 7 -> 8 , 8 -> 9 , 9-> 10
这样做有个很好的好处就是我只需要关心相邻的 2 个数据库版本的升级就可以了,比如由 9 -> 10 的时候,我只需要关心 9 如何升到 10 , 其他的低数据库版本会通过前面的代码逻辑升级到 9 。
还有一个很重要的好处就是减轻了当前开发者的工作,当前的开发者只需要关注这一次的升级就好了,之前的升级逻辑在逻辑没问题的情况下是可以很好的复用的。
但是这个有个比较明显的问题就是,如果数据量大了,那么可能升级的时候耗的时间会久一点,但是个人认为相较于开发和维护效率,这个时间可以忽略。