您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
Android打造属于自己的数据库操作类
 
来源:博客园 作者:So,Cool:2016-8-22
  1400  次浏览      16
 

1、概述

开发Android的同学都知道sdk已经为我们提供了一个SQLiteOpenHelper类来创建和管理SQLite数据库,通过写一个子类去继承它,就可以方便的创建、管理数据库。但是当我们需要去做增删改查的操作的时候,就得通过getWritableDatabase获取一个SQLiteDataBase然后老老实实去写操作值的put以及查询返回的Cursor处理,其实我们可以搞一个对象来帮我们干这些事情,打造属于你自己的数据库操作类。

2、操作类的初显形

假设现在我们什么都没有,我们要去搞一个对象来给我们干这件事情,它需要有什么才可以干呢?

那要做数据库的操作需要什么就很简单了吧?

1、要操作数据库,所以需要一个SQLiteDataBase对象,可以通过SQLiteOpenHelper的子类来获取。

2、此外数据库要创建,还需要数据库信息吧?那就直接变量引入。

3、有了数据库信息,创建了数据库,你要操作,怎么也得告诉我操作哪个表。所以还得包含创建表和更新表的信息,由于表一般会有多张,所以这里用一个数组变量。

有了信息还得交互,不然我怎么知道你要怎么创建表,所以我们在构造方法中直接获取这些信息。

接下看上面文字的代码表示


public abstract class DataBaseHelper {

/**

* 用来创建和获取数据库的SQLiteOpenHelper

*/

protected DBHelper mDbHelper;

/**

* 数据库对象

*/

protected SQLiteDatabase mDb;

/**

* 数据库信息

*/

private int mDbVersion;//版本

private String mDbName;//数据库名

/**

* 创建表语句

*/

private String[] mDbCreateSql;

/**

* 更新表语句

*/

private String[] mDbUpdateSql;
protected abstract int getMDbVersion(Context context);

protected abstract String getDbName(Context context);

protected abstract String[] getDbCreateSql(Context context);

protected abstract String[] getDbUpdateSql(Context context);

public DataBaseHelper(Context context) {

this.mDbVersion = this.getMDbVersion(context);

this.mDbName = this.getDbName(context);

this.mDbCreateSql = this.getDbCreateSql(context);

this.mDbUpdateSql = this.getDbUpdateSql(context);

this.mDbHelper = new DBHelper(context,this.mDbName,null,this.mDbVersion);

}
protected void open(){

new Thread(new Runnable() {

@Override

public void run() {

mDb = mDbHelper.getWritableDatabase();

}

}).start();

}

protected SQLiteDatabase getDB(){

return this.mDb;

}

public void close(){

this.mDb.close();

this.mDbHelper.close();

}

private class DBHelper extends SQLiteOpenHelper{

public DBHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {

super(context, name, factory, version);

}

@Override

public void onCreate(SQLiteDatabase db) {

String[] arr = DataBaseHelper.this.mDbCreateSql;

//执行创建表语句

for (int i=0;i<arr.length;i++){

String sql = arr[i];

db.execSQL(sql);

}

}

@Override

public void onUpgrade(SQLiteDatabase db,
int oldVersion, int newVersion) {

String[] arr = DataBaseHelper.this.mDbUpdateSql;

//执行更新语句

for (int i=0;i<arr.length;i++){

String sql = arr[i];

db.execSQL(sql);

}

}

}

}

 

代码比较简单,包含了进行数据库操作要用到的各种信息,并且在初始化的进行了赋值。同时还提供了SQLiteDatabase的open、close。同时在这里用到了抽象方法是因为考虑创建多个数据库的情况,让子类来提供具体的数据库信息,我只管做创建和操作就行了。

这里我们的数据库操作类已经初显雏形了,但是现在除了创建表还没什么用。操作类不提供简便的操作还叫什么操作类,下面就来说说操作。

我们要做操作类,无非是要简化操作,就像当老板一样。我告诉你一些用到的东西,你去给我完成这个事情。哈哈。

假如我现在就是要操作数据库的老板,那我其实只想告诉你必要的事情,其它的我都不想做。

那么必要的信息只有表名,要操作的字段和值,如果是删除、更新、和查询的话多加个筛选条件。接下来看代码


/**

* 统一对ContentValues处理

* @param contentValues

* @param key

* @param value

*/

private void ContentValuesPut(ContentValues
contentValues,String key,Object value){

if (value==null){

contentValues.put(key,"");

}else{

String className = value.getClass().getName();

if (className.equals("java.lang.String")){

contentValues.put(key,value.toString());

} else if (className.equals("java.lang.Integer")){

contentValues.put(key,Integer.valueOf(value.toString()));

} else if (className.equals("java.lang.Float")){

contentValues.put(key,Float.valueOf(value.toString()));

} else if (className.equals("java.lang.Double")){

contentValues.put(key,Double.valueOf(value.toString()));

} else if (className.equals("java.lang.Boolean")){

contentValues.put(key,Boolean.valueOf(value.toString()));

} else if (className.equals("java.lang.Long")){

contentValues.put(key,Long.valueOf(value.toString()));

} else if (className.equals("java.lang.Short")){

contentValues.put(key,Short.valueOf(value.toString()));

}

}

}
/**

* 根据数组的列和值进行insert

* @param tableName

* @param columns

* @param values

* @return

*/

public boolean insert(String tableName,
String[] columns,Object[] values){

ContentValues contentValues = new ContentValues();

for (int rows = 0; rows < columns.length;++rows){

ContentValuesPut(contentValues,columns[rows],values[rows]);

}

long rowId = this.mDb.insert(tableName,null,contentValues);

return rowId!=-1;

}
/**

* 根据map来进行insert

* @param tableName

* @param columnValues

* @return

*/

public boolean insert(String tableName,Map
<String,Object> columnValues){

ContentValues contentValues = new ContentValues();

Iterator iterator = columnValues.keySet().iterator();

while (iterator.hasNext()){

String key = (String) iterator.next();

this.ContentValuesPut(contentValues,
key,columnValues.get(key));

} long rowId = this.mDb.insert
(tableName,null,contentValues);

return rowId!=-1;

}

/**

* 统一对数组where条件进行拼接

* @param whereColumns

* @return

*/

private String initWhereSql
FromArray(String[] whereColumns){

StringBuffer whereStr = new StringBuffer();

for (int i=0;i<whereColumns.length;++i){

whereStr.append(whereColumns[i]).append(" = ? ");

if (i<whereColumns.length-1){

whereStr.append(" and ");

}

}

return whereStr.toString();

}

/**

* 统一对map的where条件和值进行处理

* @param whereParams

* @return

*/

private Map<String,Object>
initWhereSqlFromMap
(Map<String,String> whereParams){

Set set = whereParams.keySet();

String[] temp = new String[whereParams.size()];

int i = 0;

Iterator iterator = set.iterator();

StringBuffer whereStr = new StringBuffer();

while (iterator.hasNext()){

String key = (String) iterator.next();

whereStr.append(key).append(" = ? ");

temp[i] = whereParams.get(key);

if (i<set.size()-1){

whereStr.append(" and ");

}

i++;

}

HashMap result = new HashMap();

result.put("whereSql",whereStr);

result.put("whereSqlParam",temp);

return result;

}

/**

* 根据数组条件来update

* @param tableName

* @param columns

* @param values

* @param whereColumns

* @param whereArgs

* @return

*/

public boolean update(String tableName,String[]
columns,Object[] values,String[] whereColumns,
String[] whereArgs){

ContentValues contentValues = new ContentValues();

for (int i=0;i<columns.length;++i){

this.ContentValuesPut(contentValues,columns[i],values[i]);

}

String whereClause = this.initWhereSqlFromArray(whereColumns);

int rowNumber = this.mDb.update(tableName,contentValues,whereClause,whereArgs);

return rowNumber > 0 ;

}
/**

* 根据map值来进行update

* @param tableName

* @param columnValues

* @param whereParam

* @return

*/

public boolean update(String tableName,Map<String,Object>
columnValues,Map<String,String> whereParam){

ContentValues contentValues = new ContentValues();

Iterator iterator = columnValues.keySet().iterator();

String columns;

while (iterator.hasNext()){

columns = (String) iterator.next();

ContentValuesPut(contentValues,columns,
columnValues.get(columns));

} Map map = this.initWhereSqlFromMap(whereParam);

int rowNumber = this.mDb.update(tableName,contentValues,
(String)map.get("whereSql"),
(String[]) map.get("whereSqlParam"));

return rowNumber > 0;

}

/**

* 根据数组条件进行delete

* @param tableName

* @param whereColumns

* @param whereParam

* @return

*/

public boolean delete(String tableName,

String[] whereColumns,String[] whereParam){

String whereStr = this.initWhereSqlFromArray(whereColumns);

int rowNumber = this.mDb.delete(tableName,whereStr,whereParam);

return rowNumber > 0;

}

/**

* 根据map来进行delete

* @param tableName

* @param whereParams

* @return

*/

public boolean delete(String tableName,
Map<String,String> whereParams){

Map map = this.initWhereSqlFromMap(whereParams);

int rowNumber = this.mDb.delete(tableName,
map.get("whereSql").toString(),
(String[]) map.get("whereSqlParam"));

return rowNumber > 0;

}

/**

* 查询返回List

* @param sql

* @param params

* @return

*/

public List<Map>
queryListMap(String sql,String[] params){

ArrayList list = new ArrayList();

Cursor cursor = this.mDb.rawQuery(sql,params);

int columnCount = cursor.getColumnCount();

while (cursor.moveToNext()){

HashMap item = new HashMap();

for (int i=0;i<columnCount;++i){

int type = cursor.getType(i);

switch (type){

case 0:

item.put(cursor.getColumnName(i),null);

break;

case 1:

item.put(cursor.getColumnName(i),
cursor.getInt(i));

break;

case 2:

item.put(cursor.getColumnName(i),
cursor.getFloat(i));

break;

case 3:

item.put(cursor.getColumnName(i)
,cursor.getString(i));

break;

}

}

list.add(item);

}

cursor.close();

return list;

}

/**

* 查询单条数据返回map

* @param sql

* @param params

* @return

*/

public Map queryItemMap
(String sql,String[] params){

Cursor cursor =
this.mDb.rawQuery(sql,params);

HashMap map = new HashMap();

if (cursor.moveToNext()){

for (int i = 0;i <
cursor.getColumnCount();++i){

int type = cursor.getType(i);

switch (type){

case 0:

map.put(cursor.
getColumnName(i),null);

break;

case 1:

map.put(cursor.
getColumnName(i),cursor.getInt(i));

break;

case 2:

map.put(cursor.
getColumnName(i),cursor.getFloat(i));

break;

case 3:

map.put(cursor.
getColumnName(i),cursor.getString(i));

break;

}

}

}

cursor.close();

return map;

}
public void
execSQL(String sql){

this.mDb.execSQL(sql);

}
public void execSQL
(String sql,Object[] params){

this.mDb.execSQL(sql,params);

}

 

上面的操作代码就完毕了,这里主要对增删改的参数是数组和Map的情况进行了处理,对查询的结果进行了处理,代码比较简单也都有注释,这里就不做特别说明了。到这里一个数据库操作类就成型了。

3、操作类的继续完善

通过上面的过程已经可以使用了,那么先来看看使用,我们只需要继承操作抽象类告诉它具体的数据库信息以及建表语句。


public class TestDBHelper extends DataBaseHelper {
private static TestDBHelper mTestDBHelper;
private TestDBHelper(Context context){

super(context);

}
public static TestDBHelpe
r getInstance(Context context){

if (mTestDBHelper==null){

synchronized (DataBaseHelper.class){

if (mTestDBHelper==null){

mTestDBHelper = new TestDBHelper(context);

if (mTestDBHelper.getDB()==null||
!mTestDBHelper.getDB().isOpen()){

mTestDBHelper.open();

}

}

}

}

return mTestDBHelper;

}
@Override

protected int getMDbVersion(Context context) {

return 1;

}
@Override

protected String getDbName(Context context) {

return "test.db";

}
@Override

protected String[]
getDbCreateSql(Context context) {

String[] a = new String[1];

a[0] = "CREATE TABLE user
(id INTEGER PRIMARY KEY AUTOINCREMENT
,name TEXT,gender TEXT,age INTEGER)";

return a;

}
@Override

protected String[] getDbUpdateSql
(Context context) {

return new String[0];

}

}

 

重写父类的抽象方法告诉它数据库信息以及建表语句,然后提供一个单例供外部获取,如果没有open就open数据库,接下来看看使用

4、使用

直接获取,然后传入你想操作的表信息,So Easy!


public class MainActivity exte
nds AppCompatActivity implements View.
OnClickListener
{

private Button selectBtn;
private Button insertBtn;
private Button updateBtn;
private Button deleteBtn;
private TextView contentTv;
private TestDBHelper testDBHelper;
@Override

protected void onCreate
(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

testDBHelper = TestDBHelper.
getInstance(getApplicationContext());

selectBtn = (Button) findViewById(R.id.select_btn);

insertBtn = (Button) findViewById(R.id.insert_btn);

updateBtn = (Button) findViewById(R.id.update_btn);

deleteBtn = (Button) findViewById(R.id.delete_bt);

contentTv = (TextView) findViewById(R.id.content_tv);

selectBtn.setOnClickListener(this);

insertBtn.setOnClickListener(this);

updateBtn.setOnClickListener(this);

deleteBtn.setOnClickListener(this);

}
@Override

public void onClick(View v) {

switch (v.getId()){

case R.id.select_btn:

List<Map> list = testDBHelper.
queryListMap("select * from user",null);

contentTv.setText(String.valueOf(list));

break;

case R.id.insert_btn:

testDBHelper.insert("user",
new String[]{"name",
"gender","age"}
,new Object[]{"qiangyu",
"male",23});

break;

case R.id.update_btn:

testDBHelper.update("user",
new String[]{"name"
,"gender","age"},
new Object[]{"yangqiangyu",
"male",24},

new String[]{"name"},
new String[]{"qiangyu"});

break;

case R.id.delete_bt:

testDBHelper.delete("user",

new String[]{"name"},
new String[]{"qiangyu"});

break;

}

}

}

 

很简单了,附一张演示图
gif制作了做了压缩,图的效果不好请见谅
这里写图片描述

是不是简单多了

**yissan的博客,未经允许严禁转载 http://blog.csdn.net/yissan**

5、最后的完善

在第3步里,我们的数据库信息,和建表语句都是写在具体的代码里的,这样我们每次修改都要动代码。Android推荐我们这些具体的信息都写在配置文件xml里面,那么我们就来做一下修改。

建立一个db.xml


<?xml version="1.0" encoding="utf-8"?>

<resources>
<array name="DATABASE_INFO">

<item>test.db</item>

<item>1</item>

</array>
<array name="CREATE_TABLE_SQL">

<item>CREATE TABLE user
(id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,gender TEXT,age INTEGER)</item>

</array>
<array name="UPDATE_TABLE_SQL">

<item></item>

</array>
</resources>

 

现在的获取数据信息的代码是这样


@Override

protected int getMDbVersion(Context context) {

return Integer.valueOf(context.getResources()
.getStringArray(R.array.DATABASE_INFO)[1]);

}
@Override

protected String getDbName(Context context) {

return context.getResources().
getStringArray(R.array.DATABASE_INFO)[0];

}

@Override

protected String[]
getDbCreateSql(Context context) {

return context.getResources().
getStringArray(R.array.CREATE_TABLE_SQL);

}

@Override

protected String[]
getDbUpdateSql(Context context) {

return context.getResources().
getStringArray(R.array.UPDATE_TABLE_SQL);

}


从配置文件当中获取数据库信息,这样以后每次修改只需要修改xml文件就可以了。

6、结语

到此,一个数据库操作类就完成啦,当然你可以根据自己的需要在其实添加更多的便捷操作方法。

这里提供的操作类,在使用的时候我们还在需要在Activity中写一些查询的sql代码,我们可以再搞一个统一做各种具体操作表的对象。

   
1400 次浏览       16
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   

Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合

领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...