做Android APK应用的时候要经常和数据库打交道。在伴随着APK升级的过程中数据库可能也会有变化也要升级,我们要保证用户之前数据不流失。所以SQLite提供了onUpgrade一系列的方法来满足需求。关于数据库升级我们应该知道。
可能有人会有疑问对于数据库有升级肯定也有降级的吧。是的有的。
对于升级比如我们现在的数据库版本是3,我们肯定知道1,2两个版本的情况。数据库做了哪些具体的变化我们是明确的。所以我们在onUpdate()函数中做一些数据库变化的相应处理。这个情况我们是能控制住的。
对于数据库降级比如市面上有三个数据库的版本1,2,3 现在你想从3版本更回到2版本。因为2数据库的版本的软件是早先就发布出去的。在2数据库版本的时候我们根本就不知道3版本数据库是什么情况。根本就预知不到数据库的变化。这样这种情况没办法的办法就是重写onDowngrade()函数把当前版本(2版本)中用得到的数据库表drop(删掉)在调用onCreate() 重建一次。注意onDowngrade()重写的时候不能调用super.onDowngrade()。这个里面会抛异常。
所以可以得出一个结论。如果数据库文件不存在,只有onCreate()被调用。如果数据库文件存在,会调用onUpdate()方法升级数据库,并更新版本号。
升级过程中可能出现以下几种情况。
一. 表的创建和删除。
二. 是对某个表进行了字段的添加(注:一般加在末尾)。
三. 稍微复杂的操作,比如在修改的同时,需要进行数据的转移,那么可以采取在一个事务中执行如下语句来实现修改表的需求。
1. 将表名改为临时表(方便导入数据的时候用)
2. 创建新表(表的名字也是第一步中改名之前的名字)
3. 导入数据(把没有变的数据导入到创建的表中)
4. 删除临时表 (删除第一步中创建的临时表)
通过以上四个步骤,就可以完成旧数据库结构向新数据库结构的迁移,并且其中还可以保证数据不会应为升级而流失。
实例是基于GreenDAO数据库框架。我是直接在下面的链接代码基础上面改的。
http://blog.csdn.net/wuyuxing24/article/details/46641845
比如我们之前发布过一个1版本的数据库,现在要发布一个2版本的数据库。2版本在1版本上面做了一些小小的修改。
1版本的数据库的情况。(两个表表名是USER, HOME_SHARE_UPLOADE,默认的表名)
/** db version 1 */
private static void addCloudAccounts(Schema schema) {
Entity accounts = schema.addEntity("User");
accounts.addStringProperty("password").notNull();
accounts.addStringProperty("username").notNull().primaryKey();
accounts.addBooleanProperty("rememberPassword");
}
private static void addHomeShareUploadTableInfo(Schema schema) {
Entity uploadInfo = schema.addEntity("HomeShareUploadInfo");
uploadInfo.addIdProperty().autoincrement();
uploadInfo.addStringProperty("filename").notNull();
uploadInfo.addStringProperty("md5").notNull();
uploadInfo.addStringProperty("from").notNull();
uploadInfo.addStringProperty("to").notNull();
uploadInfo.addDateProperty("uploadTime").notNull();
uploadInfo.addIntProperty("percent");
uploadInfo.addIntProperty("state");
uploadInfo.addIntProperty("type");
}
现在要升级到2数据库的版本。做的改动如下(1. 删掉了HOME_SHARE_UPLOADE表,2. 修改了表的名字USER 改为usernewtable,3. 删掉了原来rememberPassword列,4. 新增了gender列。。我们就分这四步来update第三步稍微复杂一点点)
/** * db version 2 delete two column and add a column */
private static void addCloudAccounts(Schema schema) {
Entity accounts = schema.addEntity("User");
accounts.setTableName("usernewtable");
accounts.addStringProperty("password").notNull();
accounts.addStringProperty("username").notNull().primaryKey();
accounts.addBooleanProperty("gender");
}
GreenDAO数据库框架对应的数据库升级的代码在自动生成的代码DaoMaster类中DevOpenHelper类的方法中重写。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
for (int index = oldVersion; index < newVersion; index ++) {
switch (index) {
case 1:
db.beginTransaction();
try {
/** 1. drop HOME_SHARE_UPLOAD_INFO table */
db.execSQL("DROP TABLE IF EXISTS HOME_SHARE_UPLOAD_INFO;");
/** 2. change table name (USER -> usernewtable) */
db.execSQL("ALTER TABLE USER RENAME TO usernewtable;");
/** now table name is usernewtable */
/** 3. delete one column (REMEMBERPASSWORD) */
/** (Change the table name to temporary tables) temp table usernewtable_backup */
db.execSQL("ALTER TABLE usernewtable RENAME TO usernewtable_backup;");
/** (Create new table) */
db.execSQL("CREATE TABLE usernewtable(PASSWORD TEXT NOT NULL, USERNAME TEXT PRIMARY KEY NOT NULL);");
/** (Import data) */
db.execSQL("INSERT INTO usernewtable SELECT PASSWORD, USERNAME FROM usernewtable_backup;");
/** (Delete temp table) */
db.execSQL("DROP TABLE usernewtable_backup;");
/** 4. add one column */
db.execSQL("ALTER TABLE usernewtable ADD COLUMN GENDER INTEGER;");
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
break;
}
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
/** down grade then recreate table */
dropAllTables(db, true);
onCreate(db);
}