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客户端代码,写的真不错。文章中有不妥之处,或者性能不高之处,望各位读者不啬赐教,谢谢!