使用SQLiteOpenHelper對資料庫進行版本管理
如果應用使用到了SQLite資料庫,在使用者初次使用軟體時,需要建立應用使用到的資料庫表結構及添加一些初始化記錄,另外在軟體更新的時候,也需要對資料表結構進行更新。在Android系統,為我們提供了一個名為SQLiteOpenHelper的類,該類用于對資料庫版本進行管理,該類是一個抽象類,必須繼承它才能使用。 為了實作對資料庫版本進行管理,SQLiteOpenHelper類有兩種重要的方法,分别是onCreate(SQLiteDatabase
db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)。還可以實作public abstract void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)方法,它在每次成功打開資料庫後首先被執行,預設情況下此方法的實作為空。
當調用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法擷取用于操作資料庫的SQLiteDatabase執行個體的時候,如果資料庫不存在,Android系統會自動生成一個資料庫,接着調用onCreate()方法,onCreate()方法在初次生成資料庫時才會被調用,在onCreate()方法裡可以生成資料庫表結構及添加一些應用使用到的初始化資料。onUpgrade()方法在資料庫的版本發生變化時會被調用,資料庫的版本是由程式員控制的,假設資料庫現在的版本是1,由于業務的需要,修改了資料庫表的結構,這時候就需要更新軟體,更新軟體時希望更新使用者手機裡的資料庫表結構,為了實作這一目的,可以把原來的資料庫版本設定為2(有同學問設定為3行不行?當然可以,如果你願意,設定為100也行),并且在onUpgrade()方法裡面實作表結構的更新。當軟體的版本更新次數比較多,這時在onUpgrade()方法裡面可以根據原版号和目标版本号進行判斷,然後作出相應的表結構及資料更新。
getWritableDatabase()和getReadableDatabase()方法都可以擷取一個用于操作資料庫的SQLiteDatabase執行個體。但getWritableDatabase() 方法以讀寫方式打開資料庫,一旦資料庫的磁盤空間滿了,資料庫就隻能讀而不能寫,倘若使用的是getWritableDatabase() 方法就會出錯。getReadableDatabase()方法先以讀寫方式打開資料庫,如果資料庫的磁盤空間滿了,就會打開失敗,當打開失敗後會繼續嘗試以隻讀方式打開資料庫。但若随後再次調用此方法時,問題已經被解決,隻讀的SQLiteDatabase對象會被關閉,而重新傳回一個可讀寫的SQLiteDatabase資料庫對象。
public class DatabaseHelper extends SQLiteOpenHelper {
//類沒有執行個體化,是不能用作父類構造器的參數,必須聲明為靜态
private static final String name = "itcast"; //資料庫名稱
private static final int version = 1; //資料庫版本
public DatabaseHelper(Context context) {
//第三個參數CursorFactory指定在執行查詢時獲得一個遊标執行個體的工廠類,設定為null,代表使用系統預設的工廠類
super(context, name, null, version);
}
@Override public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement, name varchar(20), age INTEGER)");
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS person");
onCreate(db);
}
上面onUpgrade()方法在資料庫版本每次發生變化時都會把使用者手機上的資料庫表删除,然後再重新建立。一般在實際項目中是不能這樣做的,正确的做法是在更新資料庫表結構時,還要考慮使用者存放于資料庫中的資料不會丢失。
使用SQLiteOpenHelper擷取用于操作資料庫的SQLiteDatabase執行個體
......略
public class HelloActivity extends Activity {
@Override public void onCreate(Bundle savedInstanceState) {
......
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
DatabaseHelper databaseHelper = new DatabaseHelper(HelloActivity.this);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"工工", 4});
db.close();
}});
}
第一次調用getWritableDatabase()或getReadableDatabase()方法後,SQLiteOpenHelper會緩存目前的SQLiteDatabase執行個體,SQLiteDatabase執行個體正常情況下會維持資料庫的打開狀态,是以在你不再需要SQLiteDatabase執行個體時,請及時調用close()方法釋放資源。一旦SQLiteDatabase執行個體被緩存,多次調用getWritableDatabase()或getReadableDatabase()方法得到的都是同一執行個體。
使用事務操作SQLite資料庫
使用SQLiteDatabase的beginTransaction()方法可以開啟一個事務,程式執行到endTransaction() 方法時會檢查事務的标志是否為成功,如果為成功則送出事務,否則復原事務。當應用需要送出事務,必須在程式執行到endTransaction()方法之前使用setTransactionSuccessful() 方法設定事務的标志為成功,如果不調用setTransactionSuccessful() 方法,預設會復原事務。使用例子如下:
SQLiteDatabase db = ....;
db.beginTransaction();//開始事務
try {
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"工", 4});
db.execSQL("update person set name=? where personid=?", new Object[]{"工工", 1});
db.setTransactionSuccessful();//調用此方法會在執行到endTransaction() 時送出目前事務,如果不調用此方法會復原事務
} finally {
db.endTransaction();//由事務的标志決定是送出事務,還是復原事務
}
db.close();
上面兩條SQL語句在同一個事務中執行。