Android SQLite數(shù)據(jù)庫版本升級(jí)的管理實(shí)現(xiàn)
我們知道在SQLiteOpenHelper的構(gòu)造方法:
super``(Context context, String name, SQLiteDatabase.CursorFactory factory,
int
version)
中最后一個(gè)參數(shù)表示數(shù)據(jù)庫的版本號(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ù)庫版本升級(jí)的管理
當(dāng)我們項(xiàng)目剛開始的時(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ù)庫版本升級(jí)的管理實(shí)現(xiàn)
*
* 參考資料:
* [http://blog.csdn.net/guolin_blog](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ù)庫沒有執(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ù)庫沒有執(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)橛械挠脩舾揪蜎]有第一版本的APP,直接從市場下載了第二版本的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ī)上本來就有第一版本的APP舀瓢,所以在App升級(jí)到第二版本時(shí)會(huì)執(zhí)行onUpgrade(),不會(huì)執(zhí)行onCreate()
通過這樣的處理使得不同的情況下使用第二版APP時(shí)都會(huì)生成student表
又過了一個(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ù)庫沒有執(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語句窄瘟,在改語句中增加了一個(gè)字段genderid
和前面的描述類似,有的用戶第一次安裝該APP時(shí)就直接下載了第三版
2 修改版本號(hào)為3
應(yīng)對(duì)了用戶從第一版本或者第二版本升級(jí)到第三版本的情況(見下分析)
3 在onUpgrade()方法中)做了處理:當(dāng)oldVersion為2時(shí)調(diào)用 db.execSQL(ALTER_PERSON);修改person表趟卸,增加genderid字段
應(yīng)對(duì)了用戶從第二版本升級(jí)到第三版本的情況(見下分析)
注意一個(gè)問題:為什么這里的switch語句在每個(gè)case中沒有break蹄葱??锄列?
這是為了保證跨版本升級(jí)的時(shí)候每次數(shù)據(jù)庫的升級(jí)都會(huì)執(zhí)行到图云。
比如從第二版升級(jí)到第三版本,那么case 2會(huì)被執(zhí)行右蕊。
比如從第一版直接升級(jí)到第三版本琼稻,那么case 1肯定會(huì)被調(diào)用,由于沒有break所以會(huì)穿透switch語句又執(zhí)行case 2語句繼續(xù)升級(jí)饶囚,從而保證了數(shù)據(jù)的所有版本中的升級(jí)都會(huì)被執(zhí)行到帕翻。
如有疑問請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀萝风,希望能幫助到大家嘀掸,謝謝大家對(duì)本站的支持!