Android中sqlite的应用
2015-09-13 10:45
417 查看
安卓中有五种数据存储模式:
1.sharedpreferences : 一般用来存放少量配置信息,通过xml来保存,标签来取。
2.文本文档:这和就是把数据以字符串的形式存放在文本文档上。
3.content provider : 这种是通过内容提供者暴露数据,请求数据的一方可以通过约定好的Uri规则来访问数据。
4.网络存储:就是上传到网络上,像一些云服务–百度云。
5.SQLite:轻量型的数据库,通常用来存放大量的,复杂的,结构化的数据。
我们今天要介绍的就是第五种,sqlite数据存储方式。
要操作安卓系统中自带的数据库,我们要首先要继承SQLiteOpenHelper这个类,我们只有在继承这个类才能拿到数据库的对象实例。在这里我简单的继承了一下这个类,如下:
public class DBHelper extends SQLiteOpenHelper { // 构造方法 public DBHelper(Context context) { super(context, "Person.db", null, 1); } //在第一次创建数据库的时候调用,之后将不再调用这个方法。 @Override public void onCreate(SQLiteDatabase db) { String sql = "CREATE TABLE person( id VARCHAR PRIMARY KEY , name VARCHAR , age VARCHAR)"; db.execSQL(sql); } //数据库升级的时候调用的方法。 @Override public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { } }
通过上面简单的继承,我们就可以通过构造方法拿到这个数据库对象了,接下来就是对数据库的操作了。温馨提示:操作数据库之前,一定要添加权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
不过有时候我们需要在程序初始的时候就带入大量的数据,代码中放入大量的sql显然是不明智的。我们可以在PC上把数据拷过来,然后程序中复制到项目的数据库目录下面就可以了,如果这样的话,我们就应该把onCreate中的代码去掉,使用我们assets里面存放的数据库文件
/** *拷贝数据库文件到项目的数据库目录下 */ public static boolean copyDatabase(Context context, String dbName) { boolean ok = false; String directory = getDatabasePath(context); String filePath = directory + dbName; File file = new File(directory); if (!file.exists()) { file.mkdir(); } File dbFile = new File(filePath); if (dbFile.exists()) { return true; } else { InputStream is = null; OutputStream os = null; try { is = context.getAssets().open(dbName); os = new FileOutputStream(dbFile); byte[] buffer = new byte[1024 * 8]; int len = -1; while ((len = is.read(buffer)) > 0) { os.write(buffer, 0, len); } os.flush(); ok = true; is.close(); os.close(); } catch (Exception e) { ok = false; Log.i("com.cvil.sqlite.test", "asset file " + dbName + " not exits !"); } } return ok; } private static String getDatabasePath(Context context) { File defaultDBFile = context.getDatabasePath("d"); String path = defaultDBFile.getPath(); return path.substring(0, path.length() - 1); }
这段代码应该程序启动的时候就执行,也就是application类里面。在application类里面直接调用静态方法。
DBHelper.copyDatabase(this, "example.db") ;
这些操作已经全部写在PersonDao这个类里面了,下面我们就开始分析这个类吧。对数据库的操作,始终都离不开增删改查,基本都是这些操作。不管做什么,我们都必须先拿到这个数据库实例:
public PersonDao(Context context) { helper = new DBHelper(context); }
我们直接在构造方法里面创建DBHelper实例,通过SQLiteDatabase sdb = helper.getWritableDatabase() ;就可以拿到数据库了。
1.首先我们看查询方法。在这个类里面我们定义了两个全局变量,免得查询的时候传参麻烦,所以直接通过set方法给全局变量sql和parameters进行赋值查询。//添加参数 public void addParameters(String parameter) { parameters.add(parameter); } /** * 查询 * * @return */ public JSONArray query() { SQLiteDatabase sdb = helper.getReadableDatabase(); String[] args = new String[] {}; JSONArray array = new JSONArray(); try { if (StringUtils.isEmpty(sql)) { throw new Exception(NO_SQL_EXCEPTION_NAME); } if (parameters != null && parameters.size() > 0) { args = parameters.toArray(new String[parameters.size()]); } Cursor cursor = sdb.rawQuery(sql, args); JSONObject jsonObject = null; if (cursor != null && cursor.getCount() > 0) { String[] columns = cursor.getColumnNames(); for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor .moveToNext()) { jsonObject = new JSONObject(); for (String column : columns) { String tempValue = cursor.getString(cursor .getColumnIndex(column)); if (StringUtils.isNotEmpty(tempValue)) { jsonObject.put(column, cursor.getString(cursor .getColumnIndex(column))); } else { jsonObject.put(column, ""); } } array.put(jsonObject); } } } catch (Exception e) { e.printStackTrace(); } finally { sdb.close(); } return array; }
上面的代码中,Cursor cursor = sdb.rawQuery(sql, args);这一句是核心。里面的参数sql就是我们定义的全局变量,args是定义的全局变量转化而来,这个参数的含义是按顺序来替换sql中占位符”?”,也就是说,我们在setSql的时候,一定要按照顺序来addParameters,否则数据就会乱。
2.有了查询这个基本操作之后,其他操作就都变得很轻松了,我们其他很多操作都需要这个方法的辅助,我们接下来就看一下怎么获取表的详细信息。一个表的主键非常重要,因为在操作表的过程中,我们可能很多地方需要用到主键,我们先来获取一下主键,在这之前,你要熟悉“PRAGMA TABLE_INFO(table_name)”这个sql,这个可以拿到表的所有相关信息,字段,类型,是否为空,主键,外键等等。这里我们只关心主键和字段名。
/** * 获取表的新信息。 * * @param tableName * @return */ public JSONArray getTableInfo(String tableName) { this.sql = "PRAGMA TABLE_INFO ('" + tableName + "') ";//设置执行需要的sql clearParameters(); //没有占位符,不需要参数,清空参数。 return query();//执行查询。 }
我们通过上面的代码就拿到了这个表的基本信息,由JsonArray对象返回。我们通过解析这个返回的表信息就可以拿到主键字段名了。
/** * 获取主键 * * @param tableName * @return */ public String getPrimaryKey(String tableName) { String result = ""; try { JSONArray tableInfo = getTableInfo(tableName); if (tableInfo != null && tableInfo.length() > 0) { for (int i = 0; i < tableInfo.length(); i++) { JSONObject jsonItem = tableInfo.getJSONObject(i); String field = jsonItem.getString("name"); String pkValue = jsonItem.getString("pk"); if (pkValue.equals("1")) { result = field; break; } } } } catch (Exception e) { e.printStackTrace(); } return result; }
我们对拿到的JsonArray进行遍历,在“PRAGMA TABLE_INFO(table_name)”执行拿到的结果集中,每一项都会有pk和name这两个字段(因为我们现在只关心这两个),如果这个字段是主键的话,pk对应的值就是1,所以我们在看到某个字段的pkValue对应为1的时候,我们返回name对应的值,这个值就是他对应的字段了。
3.查询做的差不多了,进入主要部分了,更新和插入这个比较麻烦,有存在主键相同和不相同的情况,我们需要分别操作,不过在这之前,我们先来了解sql的插入和更新语法,有助于在后面的sql组装的理解:
插入:INSERT INTO TABLE ( PRIMARY_KEY , COLUMN_A , COLUMN_B , COLUMN_C ) VALUES ( PRIMARY_KEY_VALUE , VALUE_A ,VALUE_B ,VALUE_C ) ;
更新:UPDATE TABLE SET COLUMN_A = ‘VALUE_A’ ,COLUMN_B = ‘VALUE_B’ ,COLUMN_C = ‘VALUE_C’ WHERE PRIMARY_KEY = ‘PRIMARY_KEY_VALUE’;
/** * 组装插入语句 * @param json 插入的数据参数 * @param tableName 表名 * @param primaryKey 主键 * @return 执行的sql语句 */ private String createInsertSql(JSONObject json, String tableName,String primaryKey) { Iterator<String> keys = json.keys(); String whereColumns = ""; String whereArgs = ""; while (keys.hasNext()) { String key = keys.next(); if(key.equals(primaryKey)){ continue ; } whereColumns += "," + key; whereArgs += ",'" + json.optString(key) + "'"; } return "INSERT INTO " + tableName + "(" + whereColumns.substring(1) + ") VALUES (" + whereArgs.substring(1) + ")"; } /** * 组装更新语句 * @param json 插入的数据参数 * @param tableName 表名 * @param primaryKey 主键 * @return 执行的sql语句 */ private String createUpdateSql(JSONObject json, String tableName, String primaryKey) { Iterator<String> keys = json.keys(); String where = ""; String whereColumns = ""; while (keys.hasNext()) { String key = keys.next(); if (key.equals(primaryKey)) { where += key + " = '" + json.optString(key) + "'"; } else { whereColumns += "," + key + "='" + json.optString(key) + "'"; } } return "UPDATE " + tableName + " SET " + whereColumns.substring(1)+" WHERE " + where; }
首先将要插入的数据参数json的key放入迭代器进行循环遍历。在创建插入语句和更新语句的时候,对于主键的处理是不一样的,在插入的时候,我们是没有把主键撞到sql里面的,在更新那,我们把主键作为where条件来使用,因为我们要唯一确定一条更新的记录,我们必须通过主键来确定。在代码里面,我们再也不用担心语句的插入了,存在这条记录,他会自己去更新,不存在就插入,而实现这个判断的是:
/** * 主键值 * * @return */ private boolean isExist(String key) { boolean isExist = false; this.sql = "SELECT * FROM person WHERE id = '" + key + "' "; clearParameters(); JSONArray array = query(); if (array != null && array.length() > 0) { isExist = true; } return isExist; }
通过这个来判断是否存在主键值对应的数据。
/** * 插入 * * @param json */ public void insert(String tableName, JSONObject json) { String primaryKey = ""; try { JSONArray tableFieldInfo = getTableInfo(tableName); if (tableFieldInfo != null && tableFieldInfo.length() > 0) { for (int i = 0; i < tableFieldInfo.length(); i++) { JSONObject jsonItem = tableFieldInfo.getJSONObject(i); String pkValue = jsonItem.getString("pk"); String field = jsonItem.getString("name"); if (pkValue.equals("1")) { if (StringUtils.isEmpty(json.getString(field))) { throw new Exception("sql illeagl , primary key " + field + " is null ."); } primaryKey = field; } } String sql = ""; if (isExist(json.getString(getPrimaryKey(tableName)))) { sql = createUpdateSql(json, tableName, primaryKey); } else { sql = createInsertSql(json, tableName, primaryKey); } executeSql(sql); } } catch (Exception e) { e.printStackTrace(); } }
在上面的执行过程中注意异常的抛出,这样我们很容易的就可以在调试中定位到错误。
3.把更新和插入一起将了,现在就剩下删除了,这个其实也是最简单了的 。
/** * 删除主键值为 “id”的记录 * @param id 待删除记录的主键值。 */ public void delete(String id) { if (isExist(id)) { SQLiteDatabase sdb = helper.getWritableDatabase(); this.sql = "DELETE FROM person WHERE id = ? "; sdb.execSQL(sql, new String[] { id }); sdb.close(); } else { try { throw new Exception("data with id = " + id + " not exists "); } catch (Exception e) { e.printStackTrace(); } } }
轻松搞定。下面附上activity的代码:
package com.example.sqlitetest;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
private PersonDao dao ;
private TextView textView ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.query).setOnClickListener(this) ;
findViewById(R.id.insert).setOnClickListener(this) ;
findViewById(R.id.delete).setOnClickListener(this) ;
findViewById(R.id.getPrimaryKey).setOnClickListener(this) ;
textView = (TextView) findViewById(R.id.text) ;
dao = new PersonDao(this) ;
}
public void onClick(View v) {
String sql ;
switch (v.getId()) {
case R.id.query:
sql = "SELECT * FROM person " ;
dao.setSql(sql);
dao.clearParameters() ;
JSONArray array = dao.query() ;
textView.setText(String.valueOf(array)) ;
break;
case R.id.insert:
JSONObject json = new JSONObject() ;
try{
json.put("id", String.valueOf(System.currentTimeMillis()));
json.put("name", "caoweiwww");
json.put("age", "2c");
dao.insert(PersonDao.TABLE_NAME,json) ;
}catch (Exception e) {
e.printStackTrace() ;
}
break ;
case R.id.delete:
dao.delete("4356fd");
break ;
case R.id.getPrimaryKey:
String primaryKey = dao.getPrimaryKey("person");
if(StringUtils.isNotEmpty(primaryKey)){
textView.setText(primaryKey);
}
break ;
}
}
}
//以下是PersonDao完整代码
package com.example.sqlitetest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class PersonDao {
private DBHelper helper;
private String sql;
public static final String TABLE_NAME = "person";
private List<String> parameters = new ArrayList<String>();
private static final String NO_SQL_EXCEPTION_NAME = "sql is illeagl , set the sql please .";
public PersonDao() {
this(null, null);
}
public PersonDao(String sql) {
this(sql, null);
}
public PersonDao(String sql, List<String> parameters) {
this.sql = sql;
this.parameters = parameters;
}
public void setSql(String sql) {
this.sql = sql;
}
public void addParameters(String parameter) {
parameters.add(parameter);
}
public void setParameters(List<String> parameters) {
this.parameters = parameters;
}
public PersonDao(Context context) { helper = new DBHelper(context); }
/** * 插入 * * @param json */ public void insert(String tableName, JSONObject json) { String primaryKey = ""; try { JSONArray tableFieldInfo = getTableInfo(tableName); if (tableFieldInfo != null && tableFieldInfo.length() > 0) { for (int i = 0; i < tableFieldInfo.length(); i++) { JSONObject jsonItem = tableFieldInfo.getJSONObject(i); String pkValue = jsonItem.getString("pk"); String field = jsonItem.getString("name"); if (pkValue.equals("1")) { if (StringUtils.isEmpty(json.getString(field))) { throw new Exception("sql illeagl , primary key " + field + " is null ."); } primaryKey = field; } } String sql = ""; if (isExist(json.getString(getPrimaryKey(tableName)))) { sql = createUpdateSql(json, tableName, primaryKey); } else { sql = createInsertSql(json, tableName, primaryKey); } executeSql(sql); } } catch (Exception e) { e.printStackTrace(); } }
private void executeSql(String sql) {
SQLiteDatabase sdb = helper.getWritableDatabase();
sdb.execSQL(sql);
sdb.close();
}
public void executeBatchSql(String[] sqls) {
SQLiteDatabase sdb = helper.getWritableDatabase();
for (String sql : sqls) {
sdb.execSQL(sql);
}
sdb.close();
}
/**
* 删除主键值为 “id”的记录
* @param id 主键值。
*/
public void delete(String id) {
if (isExist(id)) {
SQLiteDatabase sdb = helper.getWritableDatabase();
this.sql = "DELETE FROM person WHERE id = ? ";
sdb.execSQL(sql, new String[] { id });
sdb.close();
} else {
try {
throw new Exception("data with id = " + id + " not exists ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 组装插入语句
*
* @param json
* 插入的数据参数
* @param tableName
* 表名
* @param primaryKey
* 主键
* @return 执行的sql语句
*/
private String createInsertSql(JSONObject json, String tableName,
String primaryKey) {
Iterator<String> keys = json.keys();
String whereColumns = "";
String whereArgs = "";
while (keys.hasNext()) {
String key = keys.next();
if (key.equals(primaryKey)) {
continue;
}
whereColumns += "," + key;
whereArgs += ",'" + json.optString(key) + "'";
}
return "INSERT INTO " + tableName + "(" + whereColumns.substring(1)
+ ") VALUES (" + whereArgs.substring(1) + ")";
}
/**
* 组装更新语句
*
* @param json
* 插入的数据参数
* @param tableName
* 表名
* @param primaryKey
* 主键
* @return 执行的sql语句
*/
private String createUpdateSql(JSONObject json, String tableName,
String primaryKey) {
Iterator<String> keys = json.keys();
String where = "";
String whereColumns = "";
while (keys.hasNext()) {
String key = keys.next();
if (key.equals(primaryKey)) {
where += key + " = '" + json.optString(key) + "'";
} else {
whereColumns += "," + key + "='" + json.optString(key) + "'";
}
}
return "UPDATE " + tableName + " SET " + whereColumns.substring(1)
+ " WHERE " + where;
}
/** * 主键值 * * @return */ private boolean isExist(String key) { boolean isExist = false; this.sql = "SELECT * FROM person WHERE id = '" + key + "' "; clearParameters(); JSONArray array = query(); if (array != null && array.length() > 0) { isExist = true; } return isExist; }
/** * 获取主键 * * @param tableName * @return */ public String getPrimaryKey(String tableName) { String result = ""; try { JSONArray tableInfo = getTableInfo(tableName); if (tableInfo != null && tableInfo.length() > 0) { for (int i = 0; i < tableInfo.length(); i++) { JSONObject jsonItem = tableInfo.getJSONObject(i); String field = jsonItem.getString("name"); String pkValue = jsonItem.getString("pk"); if (pkValue.equals("1")) { result = field; break; } } } } catch (Exception e) { e.printStackTrace(); } return result; }
/**
* 获取主键列表
*
* @param tableName
* @return
*/
public List<String> getPrimaryKeyList(String tableName) {
List<String> result = new ArrayList<String>();
try {
JSONArray tableInfo = getTableInfo(tableName);
if (tableInfo != null && tableInfo.length() > 0) {
for (int i = 0; i < tableInfo.length(); i++) {
JSONObject jsonItem = tableInfo.getJSONObject(i);
String field = jsonItem.getString("NAME");
String pkValue = jsonItem.getString("PK");
if (pkValue.equals("1")) {
result.add(field);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取表的各字段
*
* @param tableName
* 表名
* @return
*/
public List<String> getTableFieldList(String tableName) {
List<String> result = new ArrayList<String>();
try {
JSONArray tableInfo = getTableInfo(tableName);
if (tableInfo != null && tableInfo.length() > 0) {
for (int i = 0; i < tableInfo.length(); i++) {
JSONObject jsonItem = tableInfo.getJSONObject(i);
String field = jsonItem.getString("NAME");
result.add(field);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取表的新信息。
*
* @param tableName
* @return
*/
public JSONArray getTableInfo(String tableName) {
this.sql = "PRAGMA TABLE_INFO ('" + tableName + "') ";
clearParameters();
return query();
}
/**
* 清除参数
*/
public void clearParameters() {
parameters.clear();
}
/**
* 查询
*
* @return
*/
public JSONArray query() {
SQLiteDatabase sdb = helper.getReadableDatabase();
String[] args = new String[] {};
JSONArray array = new JSONArray();
try {
if (StringUtils.isEmpty(sql)) {
throw new Exception(NO_SQL_EXCEPTION_NAME);
}
if (parameters != null && parameters.size() > 0) {
args = parameters.toArray(new String[parameters.size()]);
}
Cursor cursor = sdb.rawQuery(sql, args);
JSONObject jsonObject = null;
if (cursor != null && cursor.getCount() > 0) {
String[] columns = cursor.getColumnNames();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor
.moveToNext()) {
jsonObject = new JSONObject();
for (String column : columns) {
String tempValue = cursor.getString(cursor
.getColumnIndex(column));
if (StringUtils.isNotEmpty(tempValue)) {
jsonObject.put(column, cursor.getString(cursor
.getColumnIndex(column)));
} else {
jsonObject.put(column, "");
}
}
array.put(jsonObject);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sdb.close();
}
return array;
}
}
相关文章推荐
- 解决android studio adb not responding 的问题
- Android读写assets、raw、sdard和工程文件的方法
- Android 最热的高速发展框架XUtils
- android:src
- 处理运行时状态的改变
- android 有效载荷大图,避OOM
- android SQLite学习手册
- 还在用XListView?试试更漂亮的AutoLoadListView吧!
- 收集的Android开源框架及其地址
- Android 屏幕适配dp,sp
- Android(java)学习笔记238:多媒体之图片画画板案例
- Android中获取内外存储卡位置的方法
- android 编译环境 libgl1-mesa-glx:i386相关安装后ubuntu启动失败
- Android开发框架xUtils简介(附有不使用findViewById的方法)
- Android中146种颜色对应的xml色值
- Gradle 载入中 Android 下一个.so档
- Ubuntu 下载 & 编译 Android5.1 源码
- Android 关于inflate
- 基于 Android蓝牙4.0开发详细讲解,与硬件通信 史上最牛逼,最详细
- Android应用进程间通信之Messenger信使使用及源码浅析