常用的建立數(shù)據(jù)庫(kù)的方法,即在代碼中進(jìn)行對(duì)數(shù)據(jù)庫(kù)的建立。在程序運(yùn)行過(guò)程中,當(dāng)程序需要進(jìn)行數(shù)據(jù)庫(kù)操作時(shí),應(yīng)用程序會(huì)首先嘗試打開(kāi)數(shù)據(jù)庫(kù),此時(shí)如果數(shù)據(jù)庫(kù)并不存在,程序則會(huì)自動(dòng)建立數(shù)據(jù)庫(kù),然后再打開(kāi)數(shù)據(jù)庫(kù)。在編程實(shí)現(xiàn)時(shí),一般將所有對(duì)數(shù)據(jù)庫(kù)的操作都封裝在類中,因此只要調(diào)用這個(gè)類,就可以完成對(duì)數(shù)據(jù)庫(kù)的添加、更新、刪除和查詢等操作。下面我們就來(lái)介紹一些常用的接口和類。
本文主要介紹一下如何通過(guò)SQLiteOpenHelper類來(lái)實(shí)現(xiàn)建立數(shù)據(jù)庫(kù)。
SQLiteOpenHelper是一個(gè)抽象的輔助類(Helper),用來(lái)打開(kāi)(若數(shù)據(jù)庫(kù)已存在)或創(chuàng)建數(shù)據(jù)庫(kù)。當(dāng)在程序當(dāng)中調(diào)用SQLiteOpenHelper的getWritableDatabase()方法,或者getReadableDatabase()方法的時(shí)候,這兩個(gè)方法根據(jù)數(shù)據(jù)庫(kù)是否存在、版本號(hào)和是否可寫等情況,決定在返回?cái)?shù)據(jù)庫(kù)對(duì)象前是否需要建立數(shù)據(jù)庫(kù),如果當(dāng)時(shí)沒(méi)有數(shù)據(jù),那么Android系統(tǒng)就會(huì)自動(dòng)生成一個(gè)數(shù)據(jù)庫(kù)。關(guān)于抽象類我們都知道,如果要使用它,一定是繼承它。所以使用它都是通過(guò)自己定義一個(gè)類繼承于它并實(shí)現(xiàn)其抽象方法:onCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase, int, int),onOpen(SQLiteDatabase)3個(gè)方法,如表7-6所示。
表7-6 SQLiteOpenHelper類中重要方法
方法 |
描述 |
onCreate(SQLiteDatabase) |
在數(shù)據(jù)庫(kù)第一次生成的時(shí)候會(huì)調(diào)用這個(gè)方法,一般在這個(gè)方法里邊生成數(shù)據(jù)庫(kù)表 |
onUpgrade(SQLiteDatabase,int,int) |
當(dāng)數(shù)據(jù)庫(kù)需要升級(jí)的時(shí)候,Android系統(tǒng)會(huì)主動(dòng)地調(diào)用這個(gè)方法。一般在這個(gè)方法里邊刪除數(shù)據(jù)表,并建立新的數(shù)據(jù)表,當(dāng)然是否還需要做其他的操作,完全取決于應(yīng)用的需求 |
onOpen(SQLiteDatabase) |
這是當(dāng)打開(kāi)數(shù)據(jù)庫(kù)時(shí)的回調(diào)函數(shù),一般也不會(huì)用到 |
下面通過(guò)對(duì)DBAdapter封裝類的代碼來(lái)學(xué)習(xí)如何通過(guò)繼承SQLiteOpenHelper類來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的建立、打開(kāi)和關(guān)閉等操作。
代碼清單7-34 DBAdapter
public class DBAdapter {
//聲明了數(shù)據(jù)庫(kù)的基本信息
//數(shù)據(jù)庫(kù)文件的名稱
private static final String DB_NAME = "people.db";
//數(shù)據(jù)庫(kù)表格名稱和數(shù)據(jù)庫(kù)版本
private static final String DB_TABLE = "peopleinfo";
private static final int DB_VERSION = 1;
//數(shù)據(jù)庫(kù)表中的屬性名稱
public static final String KEY_ID = "_id";
public static final String KEY_NAME = "name";
public static final String KEY_AGE = "age";
public static final String KEY_HEIGHT = "height";
//聲明SQLiteDatabase對(duì)象db
private SQLiteDatabase db;
private final Context context;
//DBOpenHelper繼承了SQLiteOpenHelper,聲明DBOpenHelper類對(duì)象,
//輔助建立、更新和打開(kāi)數(shù)據(jù)庫(kù)
private DBOpenHelper dbOpenHelper;
private static class DBOpenHelper extends SQLiteOpenHelper {}
public DBAdapter(Context _context) {
context = _context;
}
//調(diào)用了SQLiteOpenHelper類的getWritableDatabase()方法和getReadableDatabase()方法,打開(kāi)數(shù)據(jù)庫(kù)
public void open() throws SQLiteException {
dbOpenHelper = new DBOpenHelper(context, DB_NAME, null, DB_VERSION);
try {
//負(fù)責(zé)得到一個(gè)可寫的SQLite數(shù)據(jù)庫(kù),如果這個(gè)數(shù)據(jù)庫(kù)還沒(méi)有
//建立,那么mOpenHelper輔助類負(fù)責(zé)建立這個(gè)數(shù)據(jù)庫(kù)。如果數(shù)
//據(jù)庫(kù)已經(jīng)建立,那么直接返回一個(gè)可寫的數(shù)據(jù)庫(kù)
db = dbOpenHelper.getWritableDatabase();
}catch (SQLiteException ex) {
db = dbOpenHelper.getReadableDatabase();
}
}
public void close() {
if (db != null){
//關(guān)閉數(shù)據(jù)庫(kù)
db.close();
db = null;
}
}
}
如代碼清單7-34所示,我們注意到,在聲明了數(shù)據(jù)庫(kù)基本信息后,緊接著聲明了SQLiteDatabase對(duì)象db。這里的SQLiteDatabase類是由Android提供的封裝了一些數(shù)據(jù)庫(kù)操作的API的類,使用該類可以完成對(duì)數(shù)據(jù)進(jìn)行添加(Create)、查詢(Retrieve)、更新(Update)和刪除(Delete)操作(這些操作簡(jiǎn)稱為CRUD),執(zhí)行SQL命令,對(duì)數(shù)據(jù)進(jìn)行管理等工作。在下一節(jié)的數(shù)據(jù)操作中,將對(duì)使用該類實(shí)現(xiàn)數(shù)據(jù)操作進(jìn)行具體講解。
之前有講解到,繼承SQLiteOpenHelper類覆蓋其抽象方法,這里來(lái)覆蓋onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)。為了實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)進(jìn)行管理,重載onCreate()方法和onUpgrade()方法的代碼如代碼清單7-35所示。
代碼清單7-35 DBOpenHelper
private static class DBOpenHelper extends SQLiteOpenHelper {
public DBOpenHelper(Context context, String name,
CursorFactory factory, int version){
super(context, name, factory, version);
}
private static final String DB_CREATE = "create table " + DB_TABLE +
"("+KEY_ID+" integer primary key autoincrement, "+
KEY_NAME+" text not null, "+KEY_AGE+" integer,"+
KEY_HEIGHT + " float);";
@Override
public void onCreate(SQLiteDatabase _db) {
db.execSQL(DB_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {
_db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
onCreate(_db);
}
}
在上述代碼中,在聲明了創(chuàng)建表的SQL命令語(yǔ)DB_CREATE之后,分別重載了onCreate()方法和onUpgrade()方法,這是繼承SQLiteOpenHelper類必須重載的兩個(gè)方法。
onCreate()方法在數(shù)據(jù)庫(kù)第一次建立時(shí)被調(diào)用,一般用來(lái)創(chuàng)建數(shù)據(jù)庫(kù)中的表,并做適當(dāng)?shù)某跏蓟ぷ,在onCreate()方法中,通過(guò)調(diào)用SQLiteDatabase對(duì)象的execSQL()方法,執(zhí)行創(chuàng)建表的SQL命令。
onUpgrade()方法在數(shù)據(jù)庫(kù)需要升級(jí)時(shí)被調(diào)用,一般用來(lái)刪除舊的數(shù)據(jù)庫(kù)表,并將數(shù)據(jù)轉(zhuǎn)移到新版本的數(shù)據(jù)庫(kù)表中。為了簡(jiǎn)單起見(jiàn),在本段代碼的onUpgrade()方法中,并沒(méi)有做任何的數(shù)據(jù)轉(zhuǎn)移,而僅僅刪除原有的表后建立新的數(shù)據(jù)庫(kù)表。
程序開(kāi)發(fā)人員不應(yīng)直接調(diào)用onCreate()和onUpgrade()方法,而應(yīng)該由SQLiteOpenHelper類來(lái)決定何時(shí)調(diào)用這兩個(gè)方法。SQLiteOpenHelper類的getWritableDatabase()方法和getReadableDatabase()方法是可以直接調(diào)用的方法。getWritableDatabase()方法用來(lái)建立或打開(kāi)可讀/寫的數(shù)據(jù)庫(kù)對(duì)象,一旦方法調(diào)用成功,數(shù)據(jù)庫(kù)對(duì)象將被緩存,何時(shí)需要使用數(shù)據(jù)庫(kù)對(duì)象,都可以調(diào)用這個(gè)方法獲取到數(shù)據(jù)庫(kù)對(duì)象,但一定要在不使用時(shí)調(diào)用close()方法關(guān)閉數(shù)據(jù)庫(kù)。如果保存數(shù)據(jù)庫(kù)文件的磁盤空間已滿,調(diào)用getWritableDatabase()方法則無(wú)法獲得可讀/寫的數(shù)據(jù)庫(kù)對(duì)象,這時(shí)可以調(diào)用getReadableDatabase()方法,獲得一個(gè)只讀的數(shù)據(jù)庫(kù)對(duì)象。
如果程序開(kāi)發(fā)人員不希望使用SQLiteOpenHelper類,同樣可以通過(guò)SQLiteDatabase對(duì)象直接創(chuàng)建數(shù)據(jù)庫(kù)。通過(guò)SQLiteDatabase(android.database.sqlite.SQLiteDatabase)這個(gè)類,除了可以實(shí)現(xiàn)數(shù)據(jù)庫(kù)的創(chuàng)建或打開(kāi)以外,還可以進(jìn)行創(chuàng)建表、插入數(shù)據(jù)、刪除數(shù)據(jù)、查詢數(shù)據(jù)、修改數(shù)據(jù)等操作,如表7-7所示。
表7-7 SQLiteDatabase類中重要方法
方法 |
描述 |
public static SQLiteDatabase openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory) |
用于打開(kāi)或創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)(對(duì)于sqlite來(lái)說(shuō),就是打開(kāi)或產(chǎn)生一個(gè)數(shù)據(jù)庫(kù)文件),參數(shù)中的File類就是java中表示系統(tǒng)文件路徑的File類,而SQLiteDatabase.CursorFactory則是一個(gè)產(chǎn)生Cursor對(duì)象的工廠類 |
public long insert (String table, String nullColumnHack, ContentValues values) |
用于在數(shù)據(jù)庫(kù)中加入數(shù)據(jù)。ContentValue類似于java中HashMap類,用于以鍵值對(duì)的方式保存數(shù)據(jù) |
public int delete (String table, String whereClause, String[] whereArgs) |
刪除表中的數(shù)據(jù) |
public Cursor query (booleandistinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) |
查詢數(shù)據(jù)庫(kù)中的數(shù)據(jù) |
public int update (String table, ContentValues values, String whereClause, String[] whereArgs) |
用于修改數(shù)據(jù) |
public void execSQL (String sql) |
執(zhí)行String表示的非查詢的SQL語(yǔ)句,例如Create等 |
public void close () |
用來(lái)關(guān)閉數(shù)據(jù)庫(kù)并釋放數(shù)據(jù)庫(kù)占用的相關(guān)資源 |
通過(guò)SQLiteDatabase對(duì)象直接創(chuàng)建數(shù)據(jù)庫(kù)方法如下:首先調(diào)用openOrCreateDatabases()方法創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象,然后執(zhí)行SQL命令建立數(shù)據(jù)庫(kù)中的表和直接的關(guān)系。示例代碼如代碼清單7-36所示。
代碼清單7-36 openOrCreateDatabases()方法創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象
private static final String DB_CREATE = "create table " +
DB_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " +
KEY_NAME+ " text not null, " + KEY_AGE+ " integer, " + KEY_HEIGHT + " float); ";
public void create() {
db.openOrCreateDatabases(DB_NAME, context.MODE_PRIVATE, null)
db.execSQL(DB_CREATE);