Android中sqlite的应用

安卓中有五种数据存储模式:

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

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值