Android中的數據庫操作
在寫這篇文章時,數據庫部分的封裝實現主要是參照開源軟件eoe客戶端中數據庫來設計,很感謝該開源代碼,讓我又學習到了很多,如果eoe的開發人員看到這篇文章也希望多多指教。
Android中數據庫大家應該都知道了,主要是採用輕量級的開源數據庫Sqlite來實現,至於該數據庫的一些字段介紹可以參照該篇博客 http://blog.csdn.net/nieweilin/article/details/5919013,或者直接百度搜索即可。
接下來將介紹如何把我們的數據庫查詢部分的代碼進行封裝,可以重複使用。
1、 首先是創建抽象類DatabaseColumn,該類是從基類BaseColumns進行派生,主要是用來表示數據庫中表的抽象基類。
package com.busleep.db;
import java.util.ArrayList;
import java.util.Map;
import android.net.Uri;
import android.provider.BaseColumns;
//數據庫表的抽象基類;
public abstract class DatabaseColumn implements BaseColumns {
/**
* The identifier to indicate a specific ContentProvider
*/
public static final String AUTHORITY="com.busleep.provider";
/**
* The database's name
*/
public static final String DATABASE_NAME="busleep.db";
/**
* The version of current database
*/
public static final int DATABASE_VERSION = 1;
/**
* Classes's name extends from this class<span style="color:#FF0000;">(基類對象的擴展,下面的AlarmCloumn是實現基類的數據表,此處可以進行任意擴展,只需定義新的數據庫表即可。)</span>
*/
public static final String[] SUBCLASSES=new String[]{
"com.busleep.db.AlarmColumn"};
public String getTableCreateor(){
return getTableCreator(getTableName(), getTableMap());
}
/**
* Get sub-classes of this class.
*
* @return Array of sub-classes.
*/
@SuppressWarnings("unchecked")
public static final Class<DatabaseColumn>[] getSubClasses(){
ArrayList<Class<DatabaseColumn>> classes=new ArrayList<Class<DatabaseColumn>>();
Class<DatabaseColumn> subClass=null;
for(int i=0;i<SUBCLASSES.length;i++){
try {
subClass=(Class<DatabaseColumn>) Class.forName(SUBCLASSES[i]);
classes.add(subClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
continue;
}
}
return classes.toArray(new Class[0]);
}
/**
* Create a sentence to create a table by using a hash-map.
* 根據hash表中的值來創建一個數據庫中的表;
* @param tableName
* The table's name to create.
* @param map
* A map to store table columns info.
* @return
*/
private static final String getTableCreator(String tableName,
Map<String, String> map){
String[] keys=map.keySet().toArray(new String[0]);
String value=null;
StringBuilder creator=new StringBuilder();
creator.append("CREATE TABLE ").append(tableName).append("( ");
int length=keys.length;
for(int i=0;i<length;i++){
value=map.get(keys[i]);
creator.append(keys[i]).append(" ");
creator.append(value);
if(i < length - 1){
creator.append(",");
}
}
creator.append(")");
return creator.toString();
}
//抽象類中的三個抽象函數,子類需要實現該對象,從而可以創建子類中定義的數據庫表;
abstract public String getTableName();
abstract public Uri getTableContent();
abstract protected Map<String, String> getTableMap();
}
2、定義好了表的基類後,定義一個數據庫幫助類DBHelper:
package com.busleep.db;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
/**
* 數據庫幫助類;
* @author Render;
*
*/
public class DBHelper extends SQLiteOpenHelper{
</span><span style="font-size:14px;">
//數據庫名稱和數據庫版本號
private static final String DB_NAME="busleep";
private static final int DB_VERSION=2;
private SQLiteDatabase db;
//數據庫幫助類的單例;
private static DBHelper mdbHelper;
public static DBHelper getInstance(Context context){
if(mdbHelper==null){
mdbHelper=new DBHelper(context);
}
return mdbHelper;
}
private DBHelper(Context context){
super(context,DB_NAME,null,DB_VERSION);
}
private DBHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
this.db=db;
operateTable(db, "");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(newVersion==oldVersion){
return;
}
operateTable(db, "DROP TABLE IF EXISTS ");
onCreate(db);
}
public void operateTable(SQLiteDatabase db,String actionString){
Class<DatabaseColumn>[] columnsClasses=DatabaseColumn.getSubClasses();
DatabaseColumn columns=null;
for(int i=0;i<columnsClasses.length;i++){
try {
columns=columnsClasses[i].newInstance();
if("".equals(actionString)||actionString==null){
db.execSQL(columns.getTableCreateor());
}else {
db.execSQL(actionString+columns.getTableName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 插入數據;
* @param Table_Name
* @param values
* @return
*/
public long insert(String Table_Name,ContentValues values){
if(db==null){
db=getWritableDatabase();
}
return db.insert(Table_Name, null, values);
}
/**
* 根據Id來刪除數據;
* @param Table_Name
* @param id
* @return
*/
public int delete(String Table_Name,int id){
if(db==null){
db=getWritableDatabase();
}
return db.delete(Table_Name, BaseColumns._ID+"=?",
new String[] {String.valueOf(id)});
}
/**
* 更新數據庫中的數據;
* @param Table_Name
* @param values
* @param whereClause
* @param wherwArgs
* @return
*/
public int update(String Table_Name,ContentValues values,
String whereClause,String[] whereArgs){
if(db==null){
db=getWritableDatabase();
}
return db.update(Table_Name, values, whereClause, whereArgs);
}
/**
* 查詢數據庫;
* @param Table_Name
* @param columns
* @param whereStr
* @param whereArgs
* @return
*/
public Cursor query(String Table_Name,String[] columns,
String whereStr,String[] whereArgs){
if(db==null){
db=getReadableDatabase();
}
return db.query(Table_Name, columns, whereStr, whereArgs,null,null,null);
}
public Cursor rawQuery(String sql,String[] args){
if(db==null){
db=getReadableDatabase();
}
return db.rawQuery(sql, args);
}
public void ExecSQL(String sql){
if(db==null){
db=getWritableDatabase();
}
db.execSQL(sql);
}
public void closeDb(){
if(db!=null){
db.close();
db=null;
}
}
}
3、創建好數據庫幫助類和數據庫表基類後,接下來創建一個具體的數據庫表的實體類AlarmColumn,該實體數據表類派生於DatabaseColumn,主要實現抽象的方法,並定義好字段與創建數據時的字段因映射表即可實現該表的動態創建。
package com.busleep.db;
import java.util.HashMap;
import java.util.Map;
import android.net.Uri;
public class AlarmColumn extends DatabaseColumn{
public static final String TABLE_NAME="alarm";
public static final Uri CONTENT_URI=Uri.parse("content://"+AUTHORITY+"/"+TABLE_NAME);
//數據庫字段常量;
public static final String STATIONNAME="station_name";
public static final String DISTANCE="distance";
public static final String LONGTITUDE="longtitude";
public static final String LATITUDE="latitude";
public static final String ISON="ison";
//定義表字段與數據庫操作字段的映射表;
private static final Map<String, String> mColumnMap=new HashMap<String,String>();
static{
mColumnMap.put(_ID, "integer primary key autoincrement");
mColumnMap.put(STATIONNAME, "station_name");
mColumnMap.put(DISTANCE, "distamce");
mColumnMap.put(LONGTITUDE, "longtitude");
mColumnMap.put(LATITUDE, "latitude");
mColumnMap.put(ISON, "ison");
}
@Override
public String getTableName() {
// TODO Auto-generated method stub
return TABLE_NAME;
}
@Override
public Uri getTableContent() {
// TODO Auto-generated method stub
return CONTENT_URI;
}
@Override
protected Map<String, String> getTableMap() {
// TODO Auto-generated method stub
return mColumnMap;
}
}
4、利用DBHelper進行操作數據庫,例如插入數據到表AlarmColumn中,如下: mDBHelper=DBHelper.getInstance(getActivity());
//自定義的包含數據的對象;
MrAlarm alarm=CustomApplication.getInstance().getAlarm();
ContentValues cv=new ContentValues();
cv.put(AlarmColumn.STATIONNAME, alarm.getBusStationName());
cv.put(AlarmColumn.DISTANCE, alarm.getDistanceThreshold());
cv.put(AlarmColumn.LONGTITUDE, alarm.getLongtitude());
cv.put(AlarmColumn.LATITUDE, alarm.getLatitude());
cv.put(AlarmColumn.ISON, alarm.isOn());
mDBHelper.insert(AlarmColumn.TABLE_NAME, cv);
//同樣的查詢數據、更新數據、刪除數據等也可以直接利用DBHelper的接口來實現,並且支持任意表數據的擴展。
5、總結:本文主要是採用封裝的方式來實現數據庫中表的任意擴展,結構更加清晰並且容易理解,如果需要使用ContentProvider來實現的話,則可以直接在DBHelper的基礎上進行封裝實現。最後,再次感謝eoe社區中的開源eoe客戶端代碼,寫的真不錯。文章中有不妥之處,或者性能不高之處,望各位讀者不嗇賜教,謝謝!