Android SQLite數(shù)據(jù)庫(kù)版本升級(jí)的管理實(shí)現(xiàn)
Android SQLite數(shù)據(jù)庫(kù)版本升級(jí)的管理實(shí)現(xiàn)
我們知道在SQLiteOpenHelper的構(gòu)造方法:
super(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
中最后一個(gè)參數(shù)表示數(shù)據(jù)庫(kù)的版本號(hào).當(dāng)新的版本號(hào)大于當(dāng)前的version時(shí)會(huì)調(diào)用方法:
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
所以我們的重點(diǎn)是在該方法中實(shí)現(xiàn)SQLite數(shù)據(jù)庫(kù)版本升級(jí)的管理
當(dāng)我們項(xiàng)目剛開(kāi)始的時(shí)候第一版SQLiteOpenHelper是這樣寫的:
package cc.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Demo描述:
* SQLite數(shù)據(jù)庫(kù)版本升級(jí)的管理實(shí)現(xiàn)
*
* 參考資料:
* http://blog.csdn.net/guolin_blog
* Thank you very much
*/
public class DataBaseOpenHelper extends SQLiteOpenHelper {
private final static String DATABASE_NAME="test.db";
private static DataBaseOpenHelper mDataBaseOpenHelper;
public static final String CREATE_PERSON=
"create table person(personid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
public DataBaseOpenHelper(Context context,String name,CursorFactory factory,int version) {
super(context, name, factory, version);
}
//注意:
//將DataBaseOpenHelper寫成單例的.
//否則當(dāng)在一個(gè)for循環(huán)中頻繁調(diào)用openHelper.getWritableDatabase()時(shí)
//會(huì)報(bào)錯(cuò),提示數(shù)據(jù)庫(kù)沒(méi)有執(zhí)行關(guān)閉操作
static synchronized DataBaseOpenHelper getDBInstance(Context context) {
if (mDataBaseOpenHelper == null) {
mDataBaseOpenHelper = new DataBaseOpenHelper(context,DATABASE_NAME,null,1);
}
return mDataBaseOpenHelper;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_PERSON);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
在幾天之后根據(jù)項(xiàng)目需求,需要添加一張student表,于是DataBaseOpenHelper就出現(xiàn)了第二版:
package cc.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseOpenHelper extends SQLiteOpenHelper {
private final static String DATABASE_NAME="test.db";
private static DataBaseOpenHelper mDataBaseOpenHelper;
public static final String CREATE_PERSON=
"create table person(personid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
public static final String CREATE_STUDENT=
"create table student(studentid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
public DataBaseOpenHelper(Context context,String name,CursorFactory factory,int version) {
super(context, name, factory, version);
}
//注意:
//將DataBaseOpenHelper寫成單例的.
//否則當(dāng)在一個(gè)for循環(huán)中頻繁調(diào)用openHelper.getWritableDatabase()時(shí)
//會(huì)報(bào)錯(cuò),提示數(shù)據(jù)庫(kù)沒(méi)有執(zhí)行關(guān)閉操作
static synchronized DataBaseOpenHelper getDBInstance(Context context) {
if (mDataBaseOpenHelper == null) {
//改動(dòng)1
mDataBaseOpenHelper = new DataBaseOpenHelper(context,DATABASE_NAME,null,2);
}
return mDataBaseOpenHelper;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_PERSON);
//改動(dòng)2
db.execSQL(CREATE_STUDENT);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//改動(dòng)3
switch (oldVersion) {
case 1:
db.execSQL(CREATE_STUDENT);
default:
}
}
}
較版本一在版本二中有三處修改的地方:
1 版本號(hào)變成了2
2 在onCreate()方法中添加了代碼db.execSQL(CREATE_STUDENT);創(chuàng)建student表
因?yàn)橛械挠脩舾揪蜎](méi)有第一版本的APP,直接從市場(chǎng)下載了第二版本的App。所以當(dāng)然會(huì)執(zhí)行onCreate()而不會(huì)執(zhí)行onUpgrade()
3 在onUpgrade()做了處理:當(dāng)oldVersion為1時(shí)調(diào)用db.execSQL(CREATE_STUDENT);創(chuàng)建student表
因?yàn)橛械挠脩羰謾C(jī)上本來(lái)就有第一版本的APP,所以在App升級(jí)到第二版本時(shí)會(huì)執(zhí)行onUpgrade(),不會(huì)執(zhí)行onCreate()
通過(guò)這樣的處理使得不同的情況下使用第二版APP時(shí)都會(huì)生成student表
又過(guò)了一個(gè)月,根據(jù)項(xiàng)目變更,需要給person表添加一個(gè)字段genderid,于是DataBaseOpenHelper就出現(xiàn)了第三版:
package cc.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseOpenHelper extends SQLiteOpenHelper {
private final static String DATABASE_NAME="test.db";
private static DataBaseOpenHelper mDataBaseOpenHelper;
//改動(dòng)1
public static final String CREATE_PERSON=
"create table person(personid integer primary key autoincrement,name varchar(20),phone VARCHAR(12)),genderid integer)";
public static final String ALTER_PERSON="alter table person add column genderid integer";
public static final String CREATE_STUDENT=
"create table student(studentid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
public DataBaseOpenHelper(Context context,String name,CursorFactory factory,int version) {
super(context, name, factory, version);
}
//注意:
//將DataBaseOpenHelper寫成單例的.
//否則當(dāng)在一個(gè)for循環(huán)中頻繁調(diào)用openHelper.getWritableDatabase()時(shí)
//會(huì)報(bào)錯(cuò),提示數(shù)據(jù)庫(kù)沒(méi)有執(zhí)行關(guān)閉操作
static synchronized DataBaseOpenHelper getDBInstance(Context context) {
if (mDataBaseOpenHelper == null) {
//改動(dòng)2
mDataBaseOpenHelper = new DataBaseOpenHelper(context,DATABASE_NAME,null,3);
}
return mDataBaseOpenHelper;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_PERSON);
db.execSQL(CREATE_STUDENT);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_STUDENT);
//改動(dòng)3
case 2:
db.execSQL(ALTER_PERSON);
default:
}
}
}
較版本二在版本三中有三處修改的地方:
1 改變了CREATE_PERSON語(yǔ)句,在改語(yǔ)句中增加了一個(gè)字段genderid
和前面的描述類似,有的用戶第一次安裝該APP時(shí)就直接下載了第三版
2 修改版本號(hào)為3
應(yīng)對(duì)了用戶從第一版本或者第二版本升級(jí)到第三版本的情況(見(jiàn)下分析)
3 在onUpgrade()方法中)做了處理:當(dāng)oldVersion為2時(shí)調(diào)用 db.execSQL(ALTER_PERSON);修改person表,增加genderid字段
應(yīng)對(duì)了用戶從第二版本升級(jí)到第三版本的情況(見(jiàn)下分析)
注意一個(gè)問(wèn)題:為什么這里的switch語(yǔ)句在每個(gè)case中沒(méi)有break???
這是為了保證跨版本升級(jí)的時(shí)候每次數(shù)據(jù)庫(kù)的升級(jí)都會(huì)執(zhí)行到。
比如從第二版升級(jí)到第三版本,那么case 2會(huì)被執(zhí)行。
比如從第一版直接升級(jí)到第三版本,那么case 1肯定會(huì)被調(diào)用,由于沒(méi)有break所以會(huì)穿透switch語(yǔ)句又執(zhí)行case 2語(yǔ)句繼續(xù)升級(jí),從而保證了數(shù)據(jù)的所有版本中的升級(jí)都會(huì)被執(zhí)行到。
如有疑問(wèn)請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android實(shí)現(xiàn)Banner界面廣告圖片循環(huán)輪播(包括實(shí)現(xiàn)手動(dòng)滑動(dòng)循環(huán))
這篇文章主要介紹了Android實(shí)現(xiàn)Banner界面廣告圖片循環(huán)輪播(包括實(shí)現(xiàn)手動(dòng)滑動(dòng)循環(huán))的相關(guān)資料,需要的朋友可以參考下2016-02-02
Android使用DrawerLayout實(shí)現(xiàn)雙向側(cè)滑菜單
這篇文章主要為大家詳細(xì)介紹了Android使用DrawerLayout實(shí)現(xiàn)雙向側(cè)滑菜單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Android編程實(shí)現(xiàn)TCP、UDP客戶端通信功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)TCP、UDP客戶端通信功能,結(jié)合實(shí)例形式分析了Android實(shí)現(xiàn)TCP與UDP通訊功能的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2016-10-10
Android 實(shí)現(xiàn)夜間模式的快速簡(jiǎn)單方法實(shí)例詳解
這篇文章主要介紹了Android 實(shí)現(xiàn)夜間模式的快速簡(jiǎn)單方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android 中WallpaperManager用法實(shí)例
這篇文章主要介紹了Android 中WallpaperManager用法實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助到大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-09-09
Android AutoCompleteTextView控件基本用法示例
這篇文章主要介紹了Android AutoCompleteTextView控件基本用法,結(jié)合實(shí)例形式分析了AutoCompleteTextView控件的功能、使用方法及相關(guān)操作步驟,需要的朋友可以參考下2016-06-06
Android10.0實(shí)現(xiàn)本地音樂(lè)播放(附源碼下載)
這篇文章主要介紹了Android10.0實(shí)現(xiàn)本地音樂(lè)播放(附源碼下載),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
很贊的引導(dǎo)界面效果Android控件ImageSwitcher實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Android控件ImageSwitcher如何實(shí)現(xiàn)很贊的引導(dǎo)界面的具體代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
Android Build Variants 為項(xiàng)目設(shè)置變種版本的方法
下面小編就為大家分享一篇Android Build Variants 為項(xiàng)目設(shè)置變種版本的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01

