帶你走進(jìn)游戲開發(fā)的世界之?dāng)?shù)據(jù)庫(kù)SQLite 詳細(xì)介紹
數(shù)據(jù)庫(kù)SQLite介紹
數(shù)據(jù)庫(kù)最經(jīng)典的四個(gè)操作 添加、刪除、修改、查找,在處理大量數(shù)據(jù)的時(shí)候使用數(shù)據(jù)庫(kù)可以幫我們迅速定位當(dāng)前須要處理的數(shù)據(jù),舉個(gè)例子 好比現(xiàn)在要實(shí)現(xiàn)一個(gè)搜索功能 用數(shù)據(jù)庫(kù)的話只須要其中一個(gè)搜索條件 一個(gè)數(shù)據(jù)庫(kù)語(yǔ)句就可以迅速的在N條數(shù)據(jù)中找到我們需要的數(shù)據(jù),如果不使用數(shù)據(jù)庫(kù)那么查找起來(lái)會(huì)非常麻煩,效率大打折扣,所以在處理大量數(shù)據(jù)的時(shí)候使用數(shù)據(jù)庫(kù)是明確的選擇,在Android的開發(fā)中使用的數(shù)據(jù)庫(kù)是SQLite ,它是一個(gè)輕量級(jí)的數(shù)據(jù)庫(kù) 、非常小 、 移植性好、效率高、可靠 ,嵌入式設(shè)備因?yàn)槭艿接布l件的限制所以非常適合使用 SQLite 數(shù)據(jù)庫(kù)。
創(chuàng)建與刪除數(shù)據(jù)庫(kù)
封裝一個(gè)類去繼承SQLiteOpenHelper 在構(gòu)造函數(shù)中傳入數(shù)據(jù)庫(kù)名稱與數(shù)據(jù)庫(kù)版本號(hào),數(shù)據(jù)庫(kù)被創(chuàng)建的時(shí)候會(huì)調(diào)用onCreate(SQLiteDatabase db) 方法,數(shù)據(jù)庫(kù)版本號(hào)發(fā)生改變的時(shí)候會(huì)調(diào)用onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,可以方便的對(duì)軟件游戲升級(jí)后做出相應(yīng)處理避免覆蓋安裝數(shù)據(jù)庫(kù)發(fā)生改變產(chǎn)生的錯(cuò)誤。調(diào)用SQLiteOpenHelper 的getReadableDatabase()方法去創(chuàng)建數(shù)據(jù)庫(kù),如果數(shù)據(jù)庫(kù)不存在則創(chuàng)建 并且返回SQLiteDatabase對(duì)象,如果數(shù)據(jù)庫(kù)存在則不創(chuàng)建只返回SQLiteDatabase對(duì)象。調(diào)用deleteDatabase(DATABASE_NAME)方法 傳入數(shù)據(jù)庫(kù)名稱則可刪除數(shù)據(jù)庫(kù)。
封裝了一個(gè)DatabaseHelper類繼承SQLiteOpenHelper 我使用了設(shè)計(jì)模式中的單例模式來(lái)處理這個(gè)類,這里說一下單例模式 單例模式是常見的代碼設(shè)計(jì)模式之一 它的好處是在于避免在內(nèi)存中頻繁的實(shí)例化所以將它的對(duì)象寫成static 靜態(tài) 這樣它的對(duì)象就只有一份存在靜態(tài)內(nèi)存區(qū)使用的時(shí)候只須要通過getInstance()就可以直接拿到這個(gè)靜態(tài)對(duì)象。 - public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper mInstance = null;
/** 數(shù)據(jù)庫(kù)名稱 **/
public static final String DATABASE_NAME = "xys.db";
/** 數(shù)據(jù)庫(kù)版本號(hào) **/
private static final int DATABASE_VERSION = 1;
/**數(shù)據(jù)庫(kù)SQL語(yǔ)句 添加一個(gè)表**/
private static final String NAME_TABLE_CREATE = "create table test("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+"hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"
+ "number INTEGER);";
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**單例模式**/
static synchronized DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context);
}
return mInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
/**向數(shù)據(jù)中添加表**/
db.execSQL(NAME_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
/**可以拿到當(dāng)前數(shù)據(jù)庫(kù)的版本信息 與之前數(shù)據(jù)庫(kù)的版本信息 用來(lái)更新數(shù)據(jù)庫(kù)**/
}
/**
* 刪除數(shù)據(jù)庫(kù)
* @param context
* @return
*/
public boolean deleteDatabase(Context context) {
return context.deleteDatabase(DATABASE_NAME);
}
}
復(fù)制代碼 在這個(gè)類中使用DatabaseHelper對(duì)象 實(shí)現(xiàn)創(chuàng)建與刪除數(shù)據(jù)庫(kù)、 - public class NewSQLite extends Activity {
DatabaseHelper mDbHelper = null;
SQLiteDatabase mDb = null;
Context mContext = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.create_sql);
mContext = this;
//創(chuàng)建DatabaseHelper對(duì)象
mDbHelper = DatabaseHelper.getInstance(mContext);
//調(diào)用getReadableDatabase方法如果數(shù)據(jù)庫(kù)不存在 則創(chuàng)建 如果存在則打開
mDb= mDbHelper.getReadableDatabase();
Button button0 = (Button)findViewById(R.id.createDateBase);
button0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast.makeText(NewSQLite.this, "成功創(chuàng)建數(shù)據(jù)庫(kù)", Toast.LENGTH_LONG).show();
}
});
Button button1 = (Button)findViewById(R.id.deleteDateBase);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mDbHelper = DatabaseHelper.getInstance(mContext);
// 調(diào)用getReadableDatabase方法如果數(shù)據(jù)庫(kù)不存在 則創(chuàng)建 如果存在則打開
mDb = mDbHelper.getReadableDatabase();
// 關(guān)閉數(shù)據(jù)庫(kù)
mDbHelper.close();
// 刪除數(shù)據(jù)庫(kù)
mDbHelper.deleteDatabase(mContext);
Toast.makeText(NewSQLite.this, "成功刪除數(shù)據(jù)庫(kù)", Toast.LENGTH_LONG).show();
}
});
super.onCreate(savedInstanceState);
}
}
復(fù)制代碼 創(chuàng)建的數(shù)據(jù)庫(kù)會(huì)被保存在當(dāng)前項(xiàng)目中 databases 路徑下 具體如圖所示
添加與刪除數(shù)據(jù)庫(kù)中的表
數(shù)據(jù)庫(kù)是可以由多張數(shù)據(jù)表組成的 如果添加一張數(shù)據(jù)庫(kù)的表的話 可以使用 數(shù)據(jù)庫(kù)語(yǔ)句 create table 名稱(內(nèi)容) 來(lái)進(jìn)行添加 。這里給出一條創(chuàng)建數(shù)據(jù)庫(kù)的語(yǔ)句 。 意思是創(chuàng)建一張表 名稱為gameInfo 表中包含的字段 為 _id 為INTEGER 類型 并且遞增 name 為Text類型 hp mp 為INTEGER 默認(rèn)數(shù)值為100 number 為INTEGER 類型。 - /**創(chuàng)建一張表的SQL語(yǔ)句**/
private static final String NAME_TABLE_CREATE = "create table gameInfo("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+ "hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"
+ "number INTEGER);";
復(fù)制代碼 數(shù)據(jù)庫(kù)中刪除一張表 直接使用DROP TABLE 表名稱 就可以刪除 - /**刪除一張表的SQL語(yǔ)句**/
private static final String NAME_TABLE_DELETE = "DROP TABLE gameInfo";
復(fù)制代碼 在代碼中去執(zhí)行一條SQL語(yǔ)句 使用SQLiteDatabase對(duì)象去調(diào)用execSQL() 傳入SQL語(yǔ)句就OK了。 - mDb.execSQL(NAME_TABLE_CREATE);
復(fù)制代碼
以創(chuàng)建一張名稱為gameInfo的表為例 給出代碼實(shí)現(xiàn) - public class NewTable extends Activity {
DatabaseHelper mDbHelper = null;
SQLiteDatabase mDb = null;
Context mContext = null;
/**創(chuàng)建一張表的SQL語(yǔ)句**/
private static final String NAME_TABLE_CREATE = "create table gameInfo("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+ "hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"
+ "number INTEGER);";
/**刪除一張表的SQL語(yǔ)句**/
private static final String NAME_TABLE_DELETE = "DROP TABLE gameInfo";
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.create_table);
mContext = this;
mDbHelper = DatabaseHelper.getInstance(mContext);
mDb= mDbHelper.getReadableDatabase();
Button button0 = (Button)findViewById(R.id.createTable);
button0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
try {
mDb.execSQL(NAME_TABLE_CREATE);
Toast.makeText(NewTable.this, "成功添加數(shù)據(jù)表", Toast.LENGTH_LONG).show();
}catch(SQLiteException e) {
Toast.makeText(NewTable.this, "數(shù)據(jù)庫(kù)中已存此表", Toast.LENGTH_LONG).show();
}
}
});
Button button1 = (Button)findViewById(R.id.deleteTable);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
try {
mDb.execSQL(NAME_TABLE_DELETE);
Toast.makeText(NewTable.this, "成功刪除數(shù)據(jù)表", Toast.LENGTH_LONG).show();
}catch(SQLiteException e) {
Toast.makeText(NewTable.this, "數(shù)據(jù)庫(kù)中已無(wú)此表", Toast.LENGTH_LONG).show();
}
}
});
super.onCreate(savedInstanceState);
}
}
復(fù)制代碼 增加 刪除 修改 查詢 數(shù)據(jù)庫(kù)中的數(shù)據(jù)
使用SQLiteDatabase對(duì)象調(diào)用 insert()方法 傳入標(biāo)的名稱與ContentValues 添加的內(nèi)容 則可以向數(shù)據(jù)庫(kù)表中寫入一條數(shù)據(jù) delete ()為刪除一條數(shù)據(jù) update()為更新一條數(shù)據(jù)。
我詳細(xì)說一下查找一條數(shù)據(jù)使用的方法 query 中 跟了8個(gè)參數(shù)
public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit);
參數(shù)說明:
table:數(shù)據(jù)庫(kù)表的名稱
columns:數(shù)據(jù)庫(kù)列名稱數(shù)組 寫入后最后返回的Cursor中只能查到這里的列的內(nèi)容
selection:查詢條件
selectionArgs:查詢結(jié)果
groupBy:分組列
having:分組條件
orderBy:排序列
limit:分頁(yè)查詢限制
Cursor:返回值,將查詢到的結(jié)果都存在Cursor
Cursor是一個(gè)游標(biāo)接口,每次查詢的結(jié)果都會(huì)保存在Cursor中 可以通過遍歷Cursor的方法拿到當(dāng)前查詢到的所有信息。
Cursor的方法
moveToFirst() //將Curor的游標(biāo)移動(dòng)到第一條
moveToLast()///將Curor的游標(biāo)移動(dòng)到最后一條
move(int offset)//將Curor的游標(biāo)移動(dòng)到指定ID
moveToNext()//將Curor的游標(biāo)移動(dòng)到下一條
moveToPrevious()//將Curor的游標(biāo)移動(dòng)到上一條
getCount() //得到Cursor 總記錄條數(shù)
isFirst() //判斷當(dāng)前游標(biāo)是否為第一條記錄
isLast()//判斷當(dāng)前游標(biāo)是否為最后一條數(shù)據(jù)
getInt(int columnIndex) //根據(jù)列名稱獲得列索引ID
getString(int columnIndex)//根據(jù)索引ID 拿到表中存的字段
這里給出一個(gè)例子遍歷Cursor的例子 - private void query(SQLiteDatabase db) {
// 把整張表的所有數(shù)據(jù)query到cursor中
Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null);
//判斷cursor不為空 這個(gè)很重要
if (cursor != null) {
// 循環(huán)遍歷cursor
while (cursor.moveToNext()) {
// 拿到每一行name 與hp的數(shù)值
String name = cursor.getString(cursor.getColumnIndex("name"));
String hp = cursor.getString(cursor.getColumnIndex("hp"));
Log.v("info", "姓名是 " + name + "hp為 " + hp);
}
// 關(guān)閉
cursor.close();
}
}
復(fù)制代碼 向大家推薦一個(gè)查看數(shù)據(jù)庫(kù)的軟件非常好用, 名稱是SQLiteSpy.exe 如圖所示 打開xys.db 文件 可以清晰的看見數(shù)據(jù)庫(kù)表中儲(chǔ)存的內(nèi)容并且該軟件支持執(zhí)行SQL語(yǔ)句 可以直接在軟件中操作,我給出這款軟件的下載地址。
下載地址: - public class Newdate extends Activity {
DatabaseHelper mDbHelper = null;
SQLiteDatabase mDb = null;
Context mContext = null;
/** 數(shù)據(jù)庫(kù)字段 **/
public final static String TABLE_NAME = "test";
public final static String ID = "_id";
public final static String NAME = "name";
public final static String HP = "hp";
public final static String MP = "mp";
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.create_date);
mContext = this;
// 創(chuàng)建DatabaseHelper對(duì)象
mDbHelper = DatabaseHelper.getInstance(mContext);
// 調(diào)用getReadableDatabase方法如果數(shù)據(jù)庫(kù)不存在 則創(chuàng)建 如果存在則打開
mDb = mDbHelper.getReadableDatabase();
// 初始化 給數(shù)據(jù)庫(kù)表寫入一些信息
for (int i = 0; i < 10; i++) {
insert(NAME, "雨松MOMO" + i);
}
// 增加
Button button0 = (Button) findViewById(R.id.add);
button0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
insert(NAME, "新添加小可愛");
Toast.makeText(Newdate.this, "添加一條數(shù)據(jù)名稱為小可愛", Toast.LENGTH_LONG)
.show();
}
});
// 刪除
Button button1 = (Button) findViewById(R.id.delete);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
delete(ID, "1");
Toast.makeText(Newdate.this, "刪除一條_id=1的數(shù)據(jù)", Toast.LENGTH_LONG)
.show();
}
});
// 修改
Button button2 = (Button) findViewById(R.id.modify);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
update(NAME, "雨松MOMO3", "小可愛3");
Toast.makeText(Newdate.this, "更新名稱雨松MOMO3 為小可愛3",
Toast.LENGTH_LONG).show();
}
});
// 查找
Button button3 = (Button) findViewById(R.id.find);
button3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Cursor cursor = find(ID, "5");
String name = cursor.getString(cursor.getColumnIndex(NAME));
Toast.makeText(Newdate.this, "查找ID為5數(shù)據(jù)的名稱是 " + name,
Toast.LENGTH_LONG).show();
}
});
super.onCreate(savedInstanceState);
}
/**
* 插入一條數(shù)據(jù)
*
* @param key
* @param date
*/
public void insert(String key, String date) {
ContentValues values = new ContentValues();
values.put(key, date);
mDb.insert(TABLE_NAME, null, values);
}
/**
* 刪除一掉數(shù)據(jù)
*
* @param key
* @param date
*/
public void delete(String key, String date) {
mDb.delete(TABLE_NAME, key + "=?", new String[] { date });
}
/**
* 更新一條數(shù)據(jù)
*
* @param key
* @param oldDate
* @param newDate
*/
public void update(String key, String oldDate, String newDate) {
ContentValues values = new ContentValues();
values.put(key, newDate);
mDb.update(TABLE_NAME, values, key + "=?", new String[] { oldDate });
}
/**
* 查找一條數(shù)據(jù)
*
* @param key
* @param date
* @return
*/
public Cursor find(String key, String date) {
Cursor cursor = mDb.query(TABLE_NAME, null, key + "=?",
new String[] { date }, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
}
復(fù)制代碼 這里我在強(qiáng)調(diào)一下query中的第二個(gè)參數(shù)String [] columns , 舉個(gè)例子 當(dāng)前在數(shù)據(jù)中query 數(shù)值 如果我只想要數(shù)據(jù)中符合條件數(shù)據(jù)每一行的name字段和hp 字段 那么第二個(gè)參數(shù)就不要寫成null了。
第二個(gè)參數(shù)我寫成了new String[] {"name","hp"} 這樣的話得到的Cursor 中的數(shù)據(jù)只會(huì)存有 數(shù)據(jù)庫(kù)表中"name " 與 "hp"兩個(gè)字段 因?yàn)槠渌侄挝覀兏静恍枰灾磳懣梢源蟠筇岣叽a的效率。如果寫成null的話 Cursor 中的數(shù)據(jù)就會(huì)把數(shù)據(jù)庫(kù)表中所以的字段都保存進(jìn)去這樣在計(jì)算Cursor 的時(shí)候代碼就會(huì)消耗更多沒用的時(shí)間。
cursor.getString(0); 的意思就是拿到對(duì)應(yīng)new String[] {"name","hp"} 數(shù)組中的一個(gè)字段的內(nèi)容 意思就是拿到 數(shù)據(jù)庫(kù)字段"name"的值, cursor.getString(1);的意思就是拿到數(shù)據(jù)庫(kù)字段"hp"的值 。cursor.getString()中的ID 是完全對(duì)應(yīng)第二個(gè)參數(shù)String [] columns數(shù)組角標(biāo)。 - public void find() {
Cursor cursor = mDb.query(TABLE_NAME, new String[] {"name","hp"}, null,
null, null, null, null);
while(cursor.moveToNext()) {
String name = cursor.getString(0);
String hp = cursor.getString(1);
Log.v("info", "name is "+name);
Log.v("info", "hp is "+hp);
}
}
復(fù)制代碼 最后如果你還是覺得我寫的不夠詳細(xì) 看的不夠爽 不要緊我把源代碼的下載地址貼出來(lái) 歡迎大家一起討論學(xué)習(xí)
第八講android數(shù)據(jù)庫(kù)SQLite.rar(407.37 KB, 下載次數(shù): 958)[/I]2011-9-3 00:16 上傳點(diǎn)擊文件名 下載積分: 下載豆 -2 |