2014-10-27Android學習------SQLite資料庫操作(二)-----資料庫的建立--SQLiteHelper extends SQLiteOpenHelper
上篇有篇文章講了資料庫的操作 條件是:資料庫已經建好的了,我們只需要從裡面獲取資料(查詢)就可以了,
現在我們來看看第二種資料庫的操作:
class SQLiteHelper extends SQLiteOpenHelper
封裝一個繼承SQLiteOpenHelper類的資料庫操作類。SQLiteOpenHelper類是一個抽象的輔助類,主要用來生成一個數據庫並對資料庫的版本進行管理,在SQLiteOpenHelper類的構造方法中分別傳入Context、資料庫名稱,CursorFactory(一般傳入null,否則為預設資料庫),資料庫版本號(不能為負數)。
在SQLiteOpenHelper中首先執行的是onCreate方法(當資料庫第一次建立時),一般在這個方法裡生成資料表。
要注意的是,在建構函式時並沒有真正建立資料庫,而是在呼叫getWriteableDatabase()或者getReadableDatabase()方法的時候系統才會真正建立資料庫,
如果當時系統中不存在這個資料庫,系統會自動生成一個數據庫,然後返回SQLiteDatabase物件。
在繼承這個類的時候,要實現裡面的3個方法,其中前兩個方法是必須重寫的。
/**
* 建立表
*/
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE IF NOT EXISTS " +
TB_NAME + "(" +
CityBean.ID + " integer primary key," +
CityBean.CITY + " varchar," +
CityBean.CODE + " integer"+
")");
}
/**
* 當檢測與前一次建立資料庫版本不一樣時,先刪除表再建立新表
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + TB_NAME);// 先刪除表
onCreate(db);//再建立表
}
還有個onOpen(SQLiteDatabase db) 這個函式是:開啟資料庫時的回撥函式,一般不會用到
該類的原始碼如下:
使用這個類:import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class SQLiteHelper extends SQLiteOpenHelper { public static final String TB_NAME = "citys"; public SQLiteHelper(Context context, String name, CursorFactory factory, int version) { // version 就是 資料庫的版本號 super(context, name, factory, version); // TODO Auto-generated constructor stub } /** * 建立表 */ @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_NAME + "(" + CityBean.ID + " integer primary key," + CityBean.CITY + " varchar," + CityBean.CODE + " integer"+ ")"); } /** * 當檢測與前一次建立資料庫版本不一樣時,先刪除表再建立新表 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub db.execSQL("DROP TABLE IF EXISTS " + TB_NAME);// 先刪除表 onCreate(db);//再建立表 } /** * 變更列名 * @param db * @param oldColumn * @param newColumn * @param typeColumn */ public void updateColumn(SQLiteDatabase db, String oldColumn, String newColumn, String typeColumn){ try{ db.execSQL("ALTER TABLE " + TB_NAME + " CHANGE " + oldColumn + " "+ newColumn + " " + typeColumn ); }catch(Exception e){ e.printStackTrace(); } } }
當我們在一個activity類中使用這個資料庫的時候 步奏如下:
1.必須先定義一個類的成員變數 申明資料庫名字 宣告資料庫的版本號 宣告一個查詢結果遊標 申明一個數據庫物件
private static String DB_NAME = "mycity.db";//資料庫名字
private static int DB_VERSION = 1;//資料庫版本號
private Cursor cursor;//查詢結果遊標集
private SQLiteDatabase db;//開啟資料庫返回物件
private SQLiteHelper dbHelper;//資料庫操作類
2.在一個activity的onCreate(Bundle)裡面初始化和使用上面的變數
try{
/* 初始化並建立資料庫 */
dbHelper = new SQLiteHelper(this, DB_NAME, null, DB_VERSION);
/* 建立表 */
db = dbHelper.getWritableDatabase();//呼叫SQLiteHelper.OnCreate()
/* 查詢表,得到cursor物件 */
cursor = db.query(SQLiteHelper.TB_NAME, null, null, null, null, null, CityBean.CODE + " DESC");
cursor.moveToFirst();
while(!cursor.isAfterLast() && (cursor.getString(1) != null)){
CityBean city = new CityBean();
city.setId(cursor.getString(0));
city.setCity(cursor.getString(1));
city.setCode(cursor.getString(2));
cityList.add(city);
cursor.moveToNext();
}
}catch(IllegalArgumentException e){
//當用SimpleCursorAdapter裝載資料時,表ID列必須是_id,否則報錯column '_id' does not exist
e.printStackTrace();
//當版本變更時會呼叫SQLiteHelper.onUpgrade()方法重建表 注:表以前資料將丟失
++ DB_VERSION;
dbHelper.onUpgrade(db, --DB_VERSION, DB_VERSION);
}
3.在函式中使用:
查詢:
cursor = db.query(true, SQLiteHelper.TB_NAME,
new String[]{CityBean.ID, CityBean.CITY, CityBean.CODE},
sql,
null, null, null, null, null);
新增:
Long cityID = db.insert(SQLiteHelper.TB_NAME, CityBean.ID, values); 插入成功的話會返回一個值
修改:
db.update(SQLiteHelper.TB_NAME, values, CityBean.ID + "=" + cityList.get(POSTION).getId(), null);
刪除:
db.delete(SQLiteHelper.TB_NAME, CityBean.ID + "=" + view.getId(), null);
4.在activity銷燬之後需要關閉資料庫的:
在activity的生命週期函式onDestroy()裡面加上下面的程式碼
@Override
protected void onDestroy() {
db.delete(SQLiteHelper.TB_NAME, null, null);
super.onDestroy();
}
至此 一個簡單的資料庫操作基本完成了,下面我們來看看需要掌握的知識:
Android中每一個數據庫對建立它的應用程式包套件來說都是私有的,預設情況下其他應用程式無法直接訪問此私有資料庫。所有的資料庫檔案存放在手機中的/data/data/package_name/databases路徑下,以下是常用的與資料庫相關的函式:
那麼我們首先需要學習一下資料庫的 建立函式 開啟函式 關閉函式
返回值 |
函式 |
備註 |
static SQLiteDatabase |
create(SQLiteDatabase.CursorFactory factory) |
建立一個數據庫 factory:可選的資料庫遊標工廠類,當查詢(query)被提交時,該物件會被呼叫來例項化一個遊標。 |
static SQLiteDatabase |
openDatabase(String path,SQLiteDatabase.CursorFactory factory,int flags) |
根據提供的模式開啟一個數據庫 path:開啟或建立的資料庫檔案 factory:可選的資料庫遊標工廠類,當查詢(query)被提交時,該物件會被呼叫來例項化一個遊標。預設為null。 flags:控制資料庫的訪問模式。主要有以下幾種模式: l OPEN_READWRITE l OPEN_READONLY l CREATE_IF_NECESSARY l NO_LOCALIZED_COLLATORS |
static SQLiteDatabase |
openOrCreateDatabase(File file, SQLiteDatabase.CursorFactory factory) |
等同於openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY) |
static SQLiteDatabase |
openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory) |
等同於openDatabase(path,factory, CREATE_IF_NECESSARY) |
void |
close() |
關閉資料庫 |
boolean |
deleteDatabase(String name) |
刪除指定的資料庫 name:要關閉的資料庫的名字 |
這些函式的使用方法:
//建立資料庫
SQLiteDatabase mydataBase=SQLiteDatabase.create(new CursorFactory(){
//工廠類,一個可選工廠類,當查詢時呼叫來例項化一個遊標
@Override
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver masterQuery, String editTable,
SQLiteQuery query) {
// TODO Auto-generated method stub
return null;
}
});
//建立或開啟資料庫
SQLiteDatabase myDataBase=this.openOrCreateDatabase("myDataBase.db",
MODE_PRIVATE, new CursorFactory(){
//建立新的資料庫,名稱myDatabase,模式MODE_PRIVATE,可選的遊標工廠類
@Override
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver masterQuery, String editTable,
SQLiteQuery query) {
// TODO Auto-generated method stub
return null;
}
});
SQLiteDatabase myDataBase=this.openOrCreateDatabase("myDataBase.db",MODE_PRIVATE,null);
//關閉資料庫
myDataBase.close();
//刪除指定名稱的資料庫
this.deleteDatabase(“myDatabase.db”);
2.對資料庫表的操作 主要是建表:這個是一個非查詢操作 一般使用execSQL(sql)命令來執行
在對資料庫中的表進行相關操作時,可以使用非查詢的execSQL(String sql)來執行。示例程式碼如下:
String CREATE_TABLE = “create table table1 (_id integer primary key autoincrement,number integer,data text)”; //建立表
myDataBase.execSQL(CREATE_TABLE);
1)對錶的插入操作:
long insert(String table, String nullColumnHack, ContentValues values)
向表中插入一條資料
引數:
table:想要插入資料的表名
nullColumnHack:SQL不允許插入空行,初始化值為空時,這一列將會被顯示地賦一個null值
values:要插入的值,型別為ContentValues
ContentValues主要是存放表中的資料段,以及其對應的值,與map一樣採用名值對的形式儲存,但是它儲存的名值對中,名是一個String型別,值是基本資料型別。其使用示例如下:簡單的理解他就是鍵值對,跟map一樣,如果你看原始碼,它其實就是繼承他們並實現的。
ContentValues args = new ContentValues(); args.put(KEY_TITLE, title); args.put(KEY_BODY, body); myDataBase.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null); |
2)對錶的更新 修改操作
int update(String table, ContentValues values, String whereClause, String[] whereArgs)
修改表中的資料
table:想要修改資料的表名
values:要更新的值,使用方法看上面的例子
whereClause:可選的where子句,如果其值為null,將會修改所有的行。
whereArgs:當在whereClause中包含”?”時,如果whereArgs的值不為null,則這個陣列中的值將依次替換whereClause中出現的”?” ?就是寫sql語句佔位符
3)刪除一行資料
int delete(String table, String whereClause, String[] whereArgs)
從表中刪除一行資料
table:想要刪除資料的表名
whereClause:可選的where子句,如果其值為null,將會刪除所有的行。
whereArgs:當在whereClause中包含”?”時,如果whereArgs的值不為null,則這個陣列中的值將依次替換whereClause中出現的”?”
4)查詢表操作
Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String
orderBy, String limit)
查詢資料表
table:要查詢資料的表名
columns:要返回的列的列名陣列
selection:可選的where子句 ,如果其值為null,將會返回所有的行
selectionArgs:當在selection中包含”?”時,如果selectionArgs的值不為null,則這個陣列中的值將依次替換selection中出現的”?”
groupBy:可選的group by子句,如果其值為null,將不會對行進行分組
having:可選的having子句,如果其值為null,將會包含所有的分組
orderBy:可選的order by子句,如果其值為null,將會使用預設的排序規則
limit:可選的limit子句,如果其值為null,將不會包含limit子句
3.關於遊標Cursor學習:
Android採用遊標對從資料庫中查詢出來的結果進行隨機的讀寫訪問,在查詢資料庫後,將結果返回給遊標(即android.database.Cursor),這是查詢結果的記錄集,示意圖如下:
_id |
someNumber |
|
1 |
8 |
|
2 |
10 |
|
3 |
2 |
Cursor類常見的方法如下:
返回值 |
函式 |
備註 |
boolean |
move(int offset) |
以當前位置為參考,將Cursor移動指定數目的位置(相對位置) |
boolean |
moveToPosition(int position) |
將Cursor移動到指定位置(絕對位置) |
boolean |
moveToNext() |
將Cursor向前移動一個位置 |
boolean |
moveToLast() |
將Cursor向後移動一個位置 |
boolean |
moveToFirst() |
將Cursor移動到第一行 |
boolean |
isBeforeFirst() |
返回Cursor是否指向第一項資料之前 |
boolean |
isAfterLast() |
返回Cursor是否指向最後一項資料之後 |
boolean |
isClosed() |
返回Cursor是否關閉 |
boolean |
isFirst() |
返回Cursor是否指向第一項資料 |
boolean |
isLast() |
返回Cursor是否指向最後一項資料 |
boolean |
isNull(int columnIndex) |
返回指定位置的值是否為null |
int |
getCount() |
返回總的專案總數 |
int |
getInt(int columnIndex) |
返回指定列中的資料的int型表示 |
int |
getColumnIndex(String columnName) |
按給定的列的名字返回列的索引值,如果不存在則返回 -1 |
特別提示:
要建立一個Cursor(遊標),必須執行一個查詢,通過SQL使用rawQuery()方法或是更精心的query()方法,而不能使用execSQL(String
sql)【戴帽子】方法。以下為Cursor的使用示例:
Cursor cur=myDataBase.rawQuery("select * from test", null);
if(cur!=null){//遊標不為空
//返回給定名稱的列的基於0開始的index,如果該屬性列不存在則返回-1
//通過它們的index來檢索屬性值
int numColumn=cur.getColumnIndex("someNumber");
if(cur.moveToFirst()){ //cur.moveToFirst()讓遊標指向第一行,如果遊標指向第一行,則返回true
do {
int num=cur.getInt(numColumn);//獲得當前行該屬性的值
/*Cursor提供了不同的方法來回索不同的資料型別,例如getInt(int index)/getString(int index)等等*/
/*做一些事情*/
} while (cur.moveToNext());
/*遊標移動到下一行,如果遊標已經到達結果集中的最後,即沒有行可以移動時,則返回false*/
//其他可能移動的是 moveToPrevious() 和moveToFirst()方法
}
}
至此資料庫的函式基本學習了一篇,現在就是以後如何去熟練的使用它們了
最後還是總結下 public class SQLiteHelper extends SQLiteOpenHelper{}做法經常用到的兩個函式:
返回值 |
函式 |
備註 |
public void |
onCreate(SQLiteDatabase db) |
在資料庫第一次生成時會呼叫這個方法,一般我們在這個方法裡生成資料表 |
public void |
onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion) |
當資料庫需要升級時,系統會自動呼叫這個方法,一般我們在這個方法裡刪除資料表,並建立新的資料表,並根據實際需求做其他的操作 |
public void |
onOpen(SQLiteDatabase db) |
這是開啟資料庫時的回撥函式,一般不會用到 |