Android打造属于自己的数据库操作类。
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 initWhereSqlFromArray(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 TestDBHelper 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 extends 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代码,我们可以再搞一个统一做各种具体操作表的对象。
觉得不错别忘记点赞哟!
最后送给大家一个鸡汤,共勉
他每做一件小事的时候 他都像救命稻草一样抓着 有一天我一看 嚯 好家伙 他抱着的是已经是让我仰望的参天大树
Android打造属于自己的数据库操作类。的更多相关文章
- Android数据读取之Sqlite数据库操作
咱们书接上文,继续来说说Android数据读取,这回,我们要讲的是Sqlite数据库的相关操作.以一个实例开始吧: 首先,上图,看看做成后的效果: 大概描述:类似于浏览器的收藏夹,网站名称,网站地址, ...
- 【知识必备】ezSQL,最好用的数据库操作类,让php操作sql更简单~
最近用php做了点小东东,用上了ezSQL,感觉真的很ez,所以拿来跟大家分享一下~ ezSQL是一个非常好用的PHP数据库操作类.著名的开源博客WordPress的数据库操作就使用了ezSQL的My ...
- PHP 数据库操作类:ezSQL
EZSQL类介绍: 下载地址:http://www.jb51.net/codes/26393.htmlezsql是一个小型的快速的数据库操作类,可以让你很容易地用PHP操作各种数据库( MySQL.o ...
- 通用数据库操作类,前端easyui-datagrid,form
实现功能: 左端datagrid显示简略信息,右侧显示选中行详细信息,数据库增删改 (1)点击选中行,右侧显示详细信息,其中[新增].[修改].[删除]按钮可用,[保存]按钮禁用 (2)点击[ ...
- php : mysql数据库操作类演示
设计目标: 1,该类一实例化,就可以自动连接上mysql数据库: 2,该类可以单独去设定要使用的连接编码(set names XXX) 3,该类可以单独去设定要使用的数据库(use XXX): 4,可 ...
- php MySQL数据库操作类源代码
php MySQL数据库操作类源代码: <?php class MySQL{ private $host; //服务器地址 private $name; //登录账号 private $pwd; ...
- 一个基于PDO的数据库操作类(新) 一个PDO事务实例
<?php /* * 作者:胡睿 * 日期:2011/03/19 * 电邮:hooray0905@foxmail.com * * 20110319 * 常用数据库操作,如:增删改查,获取单条记录 ...
- ecshop数据库操作类
ECShop v2.7.2没有使用一些开源的数据库操作类,比如adodb或者PEAR,而是封装了自己的实现. 好处:实现非常轻量,只有一个文件,27Kb,大大减小了分发包的文件大小. 当网站需要做me ...
- 设计模式 - 单例模式mysql数据库操作类
待续... index.php 调用方法: <?php header('Content-Type:text/html; charset=utf8'); require 'instance.php ...
随机推荐
- 读《linux内核完全注释》的FAQ
以下只是个人看了<linux内核完全注释>的一点理解,如果有错误,欢迎指正! 1 eip中保存的地址是逻辑地址.线性地址还是物理地址? 这个应该要分情况.eip保存的是下一条要执行的指令地 ...
- ORM开发之解析lambda实现group查询(附测试例子)
目的:以编程方式实现group查询,在开发ORM时,需要达到这样的效果 先看一个简单的group语句 select BarCode,ProductName,COUNT(BarCode) as tota ...
- 改写yii2的listview功能
在vendor\yiisoft\yii2\widgets路径下新增文件ListViewtest,将下列代码粘贴并保存 <?php namespace yii\widgets; use Yii;u ...
- CSS3中惊艳的gradient
以前曾经记录过linear-gradient(线性渐变)和 radial-gradient(径向渐变)的语法. 可以参考<CSS3中border-radius.box-shadow与gradie ...
- PJAX初体验(主要是利用HTML5 新增API pushState和replaceState+AJAX)
说在前面 什么是PJAX呢? 站在应用角度的就是既实现了页面无刷新的效果,同时也产生了浏览器的前进和后退,而且url也会变化. 也不是什么新鲜技术,主要是AJAX+html5 pushState和re ...
- 【Android】直播必备之YUV使用总结 —— Android常用的几种格式:NV21/NV12/YV12/YUV420P的区别
说明 因工作方面接触到图像处理这一块,需要对手机摄像头采集的原始帧做Rotate或者Scale,但无奈对此的了解少之又少,于是网上搜了一顿,完事后将最近所学总结一下,以方便之后的人别踩太多坑. 首先想 ...
- 微信小程序(应用号)开发体验
昨天微信小程序(应用号)内测的消息把整个技术社区炸开了锅, 我也忍不住跟了几波,可惜没有内测资格,听闻破解版出来了, 今天早上就着原来的项目资源试开发了一下,总结一下体验. 总体体验 开发效率高,6: ...
- LINQ to SQL语句(13)之开放式并发控制和事务
Simultaneous Changes开放式并发控制 下表介绍 LINQ to SQL 文档中涉及开放式并发的术语: 术语 说明 并发 两个或更多用户同时尝试更新同一数据库行的情形. 并发冲突 两个 ...
- ASP.NET MVC入门之再不学习就真的out了
听说最近又出了什么SAM,MVC辉煌即将过去,惊了我一身冷汗,ASP.NET MVC是啥都还没搞明白呢 于是赶紧打开ASP.NET官网学习学习,欢迎各位高手大侠来指点指点
- [译]Godot系列教程一 - 场景与节点
场景(Scene)与节点(Node) 简介 先设想有那么一瞬间你自己不再是一名游戏开发者了,而是一名大厨! 你的装备换成了一套大厨的制服.不要考虑制作游戏的事情,你现在的职责是为你的顾客创建新的可口的 ...