转载请注明出处:
当你传入的SQLite版本与当前的SQLite版本不同时,便会执行onUpgrade方法,我们可以重写这个方法来实现我们的更新逻辑,先看源码的执行方式:
从
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
这是我们在使用SQLiteOpenHelper类时最常使用到的方法,用于打开一个可写的数据库,
getDatabaseLocked(true)//参数true表示可写、false表示打开一个只读的数据库
getDatabaseLocked(true)中,下面就是关于版本更新的逻辑:(方法中的部分代码)
final int version = db.getVersion();//获取当前的版本
if (version != mNewVersion) {//版本有变更
if (db.isReadOnly()) {//如果在一个只读的数据库中更新版本,会产生异常,这点要注意
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
db.beginTransaction();//开始事务
try {
if (version == 0) {//如果数据库不存在则创建
onCreate(db);
} else {
if (version > mNewVersion) {//新版本小于当前版本,也就是降版本时会执行这个方法,这个方法会抛出异常
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);//更新版本,我们需要重写这个方法
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
if (db.isReadOnly()) {
Log.w(TAG, "Opened " + mName + " in read-only mode");
}
mDatabase = db;
return db;
以上就是版本更新的逻辑,那我们应当如何去重写onUpgrade方法呢?四个步骤:
/**
* 更新数据库版本,例如需要将user表的id、name、sex、age字段更新为user_id,user_name,user_sex,user_age
*/
private void UpgradeV2(SQLiteDatabase db) {
StringBuffer sb1 = new StringBuffer();
//1将需要更新的user表重命名为temp_user
sb1.append(" ALTER TABLE ");
sb1.append("user");
sb1.append(" RENAME TO ");
sb1.append("temp_");
sb1.append("user");
db.execSQL(sb1.toString());
//2
db.execSQL("创建新的user表的SQL语句,表名为user");
//3将旧表(temp_user)的数据复制到新表(user)
StringBuilder sb3 = new StringBuilder();
sb3.append("INSERT INTO ");
sb3.append("user");
sb3.append("(id,name.sex.age)");
sb3.append(" SELECT ");
sb3.append("user_id,user_name_user_sex,user_age");
sb3.append(" FROM ");
sb3.append("temp_user");
db.execSQL(sb3.toString());
//4删除临时表
StringBuilder sb4 = new StringBuilder();
sb4.append(" DROP TABLE ");
sb4.append("temp_user"););
db.execSQL(sb4.toString());
}
//更新版本完成之后才会去执行你的增删改查操作
还有需要注意的一个地方是,更新的时候应当使用是如下循环的方式更新,因为如果某个用户一直不下载更新你的APK,他的数据库版本是1,而你最新版APK的数据库版本已经到了5了,为了不出错,需要循环将他的数据库版本更新到2,再更新到3,再更新到4,再更新5,这样,你的增删改查才不会出错。如下代码:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
for (int i = oldVersion; i <= newVersion; i++) {
switch (i) {
case 2:
UpgradeV2(db);
break;
case 3:
UpgradeV3(db);
break;
case 4:
UpgradeV4(db);
break;
}
}
}
有不对的地方,欢迎指出!