您的位置:首页 > 移动开发 > Android开发

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;
}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: