这是我们在使用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方法呢?四个步骤:
- <pre name="code" class="java">/**
- * 更新数据库版本,例如需要将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;
- }
- }
- }