天天看點

android版本更新到幾了,Android版本更新時對SQLite資料庫更新或者降級遇到的問題...

SQLite是Android内置的一個很小的關系型資料庫。SQLiteOpenHelper是一個用來輔助管理資料庫建立和版本更新問題的抽象類。我們可以繼承這個抽象類,實作它的一些方法來對資料庫進行自定義操作。下面兩個方法必須重寫:

public void onCreate(SQLiteDatabase db)

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

另外SQLiteOpenHelper子類在構造執行個體時必須指定目前資料庫的名稱(name)、版本号(version)。而這裡名稱就決定了資料庫存儲時的檔案名稱,而這裡的版本号與App在AndroidMainfest.xml定義的versionCode沒有絕對關聯。也就是在App更新時如果資料庫的資料結構沒有發生變化那麼資料庫的版本号則不用增加。

onCreate:調用時機是使用者首次安裝應用後啟動,或是清除App資料庫檔案後啟動。這時可以在這個函數中完成初始的資料表的建立。

onUpgrade:調用時機是使用者在做應用更新,覆寫安裝後啟動,如果新版本中資料庫版本号要比舊版本中的資料庫版本号高則會調用。這時可以在這個函數完成資料庫版本更新帶來的舊版本的相容問題,以及資料遷移問題。

還有一個一般情況下不需要重寫,但在應用出現逆向降級(如應用由版本号4降級安裝版本号為3的包)時必須重寫的方法onDowngrade,如果應用降級覆寫安裝時沒有重寫該方法則會崩潰。

在資料庫版本更新時, 我們可能會遇到這樣一些情況:

需要擴充一個表的字段

删除掉原來表上某個備援的字段

建立一個表

而處理上面這些問題都要在不損害舊資料庫曆史資料的前提下完成。這裡我們假設使用者手機上之前安裝的是資料庫版本為1的包,更新安裝的是資料庫版本号為2的包。這時我們要在資料庫版本為2的包在去處理這些更新邏輯。

首先是擴充一個表的字段在onUpgrade中的實作為:

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

//舊資料庫版本為1,才為表pedant添加一個student_name字段

if(oldVersion 

db.execSQL("ALTER TABLE pedant ADD COLUMN student_name text");

}

}

SQLite對ALTER TABLE的支援是有限的,你可以在一個存在表上添加一個字段到末尾,或者是改變表的名稱。但如果你想做更複雜的操作,比如删除一個表已有的字段,就要重新建立這個表并完成資料遷移,而不能使用DROP COLUMN這樣友善的指令了。詳見SQLite

Frequently Questions

比如表pedant原來有三個字段a、b、c,現在想删除c字段,那麼在onUpgrade中寫法如下:

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

//舊資料庫版本為1,删除表pedant的c字段

if(oldVersion 

db.beginTransaction();

try {

db.execSQL("CREATE TEMPORARY TABLE pe_backup (a, b);");

db.execSQL("INSERT INTO pe_backup SELECT a, b FROM pedant;");

db.execSQL("DROP TABLE pedant;");

db.execSQL("CREATE TABLE pedant(a text, b text);");

db.execSQL("INSERT INTO pedant SELECT a, b FROM pe_backup;");

db.execSQL("DROP TABLE pe_backup;");

db.setTransactionSuccessful();

} finally {

db.endTransaction();

}

}

}

這樣就既完成了對c字段的删除也保留了原來表上的資料。

最後一種情況最簡單直接執行CREATE語句就要可以了。

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

//舊資料庫版本為1,建立新表newtb

if(oldVersion 

db.execSQL("CREATE TABLE newtb(a text, b text);");

}

}資料庫在做更新時我們能明确地知道目前我們要對各舊表進行什麼樣的操作來相容新版本。但如果在資料庫降級時,情況就不一樣了,針對我們開發新版本2時,

我們不能明确地知道以後的新版本比如版本3、4的資料庫結構走向是怎樣的。比如以後使用者從版本3回退到我們正在開發的版本2,由于我們開發當時不能預知版本3的表結構,不知版本3的資料表能否相容到版本2(假如版本3更新時删除了一個版本2一直在用的表字段,這時回退資料結構可能就不相容了),那麼我們在開發版本2時最穩妥的做法是重寫onDowngrade時把所有目前版本将用到的表全部重建,即降級時扔掉以前全部的資料。

// 因為我們無法預知未來版本的表結構,向下相容時最穩妥的方法就是将該版本自己需要的表重構一次

@Override

public void onDowngrade (SQLiteDatabase db, int oldVersion, int newVersion) {

db.execSQL("DROP TABLE IF EXISTS t1;");

db.execSQL("DROP TABLE IF EXISTS t2;");

db.execSQL("DROP TABLE IF EXISTS t3;");

db.execSQL("DROP TABLE IF EXISTS t4;");

....

onCreate(db); // 建表

}