编程是一种快乐,这种快乐让我更加热爱生活!
昨天花了点时间整理下sqlite的学习及封装,今天把代码上传,供大家一起进步。
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.os.CancellationSignal; import android.os.OperationCanceledException; import android.util.Log; import java.util.concurrent.CancellationException; /** * Created by GM on 2017/4/5 0005 * Version V1.0.0 * Description: 《SQLite学习及封装》 * * 特点: * (1)轻量级 * (2)零配置、无服务器 * (3)单一文件、简单的访问 * (4)跨平台/可移植 * (5)弱类型的字段 * (6)开源 * (7)可变长度的记录 * (8)内存数据库 * * 数据类型: * NULL:这个值为空值 * VARCHAR:长度不固定且其最大长度为 n 的字串,n不能超过 4000 * CHAR:长度固定为n的字串,n不能超过 254 * INTEGER:值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8 * REAL:所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号 * TEXT:值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE) * BLOB:值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式 * DATA:包含了 年份、月份、日期 * TIME:包含了 小时、分钟、秒 * * 1、getWritableDatabase跟getReadableDatabase的区别: * getWritableDatabase取得的实例不是仅仅具有写的功能,而是同时具有读和写的功能; * getReadableDatabase取得的实例也是具对数据库进行读和写的功能 * * getWritableDatabase:取得的实例是以读写的方式打开数据库,如果打开的数据库磁盘满了,此时只能读不能写, * 此时调用了getWritableDatabase的实例,那么将会发生错误(异常) * getReadableDatabase:取得的实例是先调用getWritableDatabase以读写的方式打开数据库,如果数据库的磁盘满了, * 此时返回打开失败,继而用getReadableDatabase的实例以只读的方式去打开数据库 * * 2、rawQuery与query的区别: * eg:Cursor cursor = db.rawQuery("select name from *** where id=?", new String[]{"1"}); * Cursor cursor = db.query("***", new String[]{"name"}, "id=?", new String[]{"1"}, null, null, null); * 那么最后都执行rawQueryWithFactory,query相对于rawQuery出错的机率小(有时候语句写错),query是android自己封装的API * * */ public class DBUtils { //. 数据库名称 private static final String DB_NAME = "fengzhuan.db"; //. 数据库版本 private static final int DB_VERSION = 1; //. 旧版本号 private static final int OLD_VERSION = DB_VERSION; //. 新版本号 private static final int NEW_VERSION = 2; private SQLiteDatabase mDb; private DBHelper mDbHelper; private Context mContext; private static class DBHelper extends SQLiteOpenHelper { public DBHelper(Context context) { //. 第三个参数CursorFactory指定在执行查询时获得一个游标实例的工厂类,设置为null,代表使用系统默认的工厂类 super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { //. 表第一次不存在时创建 db.execSQL("create table message(id integer primary key autoincrement, mid VARCHAR(20), user VARCHAR(20)," + " title VARCHAR(255), msg VARCHAR(255), state int(1), type int(2), time VARCHAR(20));"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion==OLD_VERSION && newVersion==NEW_VERSION) { //. 版本升级后,可以实现新操作 //. eg:这里就往原来的phone表中插入age字段 db.execSQL("alter table phone add age text;"); } } //. 判断表是否存在后,再创建表 public boolean tableIsExist(String tableName){ boolean isTableExist = true; SQLiteDatabase db = getReadableDatabase(); Cursor cursor = db.rawQuery("select count(*) from sqlite_master where type='table' and name='"+tableName+"';", null); while (cursor.moveToNext()) { if (cursor.getInt(0)==0) { isTableExist=false; } } cursor.close(); db.close(); return isTableExist; } } public DBUtils(Context context) { this.mContext = context; } /** *. 打开数据库(使用getWritableDatabase不能再写入则会出现异常,因此在此做异常处理) * */ public DBUtils openDB(){ mDbHelper = new DBUtils.DBHelper(mContext); try { mDb = mDbHelper.getWritableDatabase(); }catch (SQLException e) { mDb = mDbHelper.getReadableDatabase(); Log.d("数据库磁盘已经满了,", "进入getReadableDatabase模式!"); } return this; } /** *. 关闭数据库 * */ public void closeDB(){ if(mDbHelper != null){ mDbHelper.close(); } } /** *. 判断表是否存在 * */ public boolean tableExist(String tableName) { return mDbHelper.tableIsExist(tableName); } /** *. 创建新表 * */ public void createNewTable(String createTable) { mDb.execSQL(createTable); } /** *. 插入方法 * table : 表名 * nullColumnHack: 当values参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许 * 插入一个空行),为了防止这种情况,我们要在这里指定一个列名,到时候如果发现将要 * 插入的行为空行时,就会将你指定的这个列名的值设为null,然后再向数据库中插入 * values : 通过HashMap以键值对的方式存储列值 * */ public void insert(String tableName, ContentValues values){ mDb.insert(tableName, null, values); } /** *. 查询方法 * 注解部分共学习参考,调用方法前请查看方法参数 * param number : 8 * table : 表名 * columns : 返回哪一列,如果参数是null,则返回所有列(不鼓励设置为null,以免防止读出的数据没有用到) * selection : 查询条件子句 * selectionArgs : 在selection字段中可能会用'?'的形式来加一些额外的参数,这个的selectionArgs字段就是把selection字段的条件填充好 * 用于为selection子句中占位符传入参数值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常 * groupBy : 一个过滤器,如何来分组---设置为null则不分组 * having : 分组后聚合的过滤条件 * orderBy : 排序,格式是SQL的ORDER一样.设置null使用默认(无序unonder)排列 * limit : 返回的行数,设置为null表示没有限制条款//用于进行分页 * */ public Cursor queryHaveLimit(String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit){ //. 除表名外,其余置空,默认返回全部记录 Cursor cursor = mDb.query(tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit); //. 那么就返回前面三条记录 //Cursor cursor = db.query(tableName, null, null, null, null, null, null, "3"); //. 返回指定范围内的记录 //Cursor cursor = db.query(tableName, null, null, null, null, null, null, "2,5"); //. 返回指定列记录 //Cursor cursor = db.query(tableName, new String[]{"name,number,desc"}, null, null, null, null, null, null); //. 子条件 + 子条件的具体值 //Cursor cursor = db.query(tableName, null, "_id=?", new String[]{"2"}, null, null, null, null); //. 通过列名分组,并且默认从最后一条显示到最前面 //Cursor cursor = db.query(tableName, null, null, null, "desc", null, null, null); //. 分组后,判断以sex分组后的记录数大于3的是哪些记录 //Cursor cursor = db.query(tableName, null, null, null, "sex", "count(sex)>3", null, null); //. 通过某一个列从小到大排序显示出来 //Cursor cursor = db.query(tableName, null, null, null, null, null, "number", null); return cursor; } /** * param(7) * 这里少个limit参数,其他与queryHaveLimit一样 * */ public Cursor queryNoneLimit(String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) { Cursor cursor = mDb.query(tableName, columns, selection, selectionArgs, groupBy, having, orderBy); return cursor; } /** *. distinct : 指定是否去除重复记录 * 其他参数与queryHaveLimit一样 * */ public Cursor queryHavaDistinctLimit(boolean distinct, String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) { Cursor cursor = mDb.query(distinct, tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit); return cursor; } /** *. distinct : 指定是否去除重复记录 * cancellationSignal : 取消操作信号,或者置空。如果取消了操作,那么执行查询时将抛出OperationCanceledException * */ public Cursor queryDistinctNoneLimit(boolean distinct, String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) { Cursor cursor = null; try { cursor = mDb.query(distinct, tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit, cancellationSignal); }catch (OperationCanceledException e) { e.printStackTrace(); } return cursor; } /** *. sql : 查询语句 * selectionArgs : * */ public Cursor rawQueryNormal(String sql, String[] selecttionArgs) { Cursor cursor = mDb.rawQuery(sql, selecttionArgs); //. 如下:第二个参数是具体来指定_id值是多少;若没有条件,则第二个参数为空 //Cursor cursor = db.rawQuery("select * from phone where _id=?;", new String[]{"3"}); return cursor; } /** *. sql : 查询语句 * selectionArgs : * cancellationSignal : * */ public Cursor rawQueryWithCancellationSignal(String sql, String[] selectionArgs, CancellationSignal cancellationSignal) { Cursor cursor = null; try { cursor = mDb.rawQuery(sql, selectionArgs, cancellationSignal); }catch (CancellationException e) { e.printStackTrace(); } return cursor; } /** *. 根据唯一标识_id 来删除数据 * */ public int delete(String tableName, String whereClause, String[] whereArgs){ //. 方式一 //String sql = "delete from phone where _id = 1"; //int returnValue = db.execSQL(sql); return mDb.delete(tableName, whereClause, whereArgs); } /** *. 删除表的所有数据 * */ public void deleteAllData(String tableName) { //. 方式一 //String sql = "delete from phone;"; //db.execSQL(sql); //. 方式二 mDb.delete(tableName, null, null); } /** *. 删除表 * */ public void dropTable(String sql) { //. String sql = "drop table phone;"; mDb.execSQL(sql); } /** *. 删除数据库 * */ public void deleteDB(String sql) { //. 方式1 //context.deleteDatabase(DB_NAME); //. 方式2 //. String sql = "drop database gm.db;"; mDb.execSQL(sql); } /** *. 更新数据库的内容 * table:表名 * contentValues:键值对数据 * whereClause:条件字段 * whereArgs:具体条件字段值 * */ public void update(String tableName, ContentValues values, String whereClause, String[]whereArgs){ //eg: db.update("phone", updateValues, "_id=?", new String[]{"16"}); mDb.update(tableName, values, whereClause, whereArgs); } }
在Activity中调用如下:
//. 插入 DBUtils dbUtilsAdd = new DBUtils(this); dbUtilsAdd.openDB(); ContentValues insertValues = new ContentValues(); insertValues.put("name", "person"); insertValues.put("sex", "man"); insertValues.put("number", "120"); insertValues.put("desc", "java编程"); dbUtilsAdd.insert("phone", insertValues); dbUtilsAdd.closeDB();
//. 查询 DBUtils dbUtilsSelect = new DBUtils(this); dbUtilsSelect.openDB(); Cursor selectValues = dbUtilsSelect.queryHaveLimit("message", null, null, null, null, null, null, null); while (selectValues.moveToNext()) { //. 用封装类保存读取数据 Message message = new Message( selectValues.getInt(selectValues.getColumnIndex("id")), selectValues.getString(selectValues.getColumnIndex("user")), selectValues.getString(selectValues.getColumnIndex("mid")), selectValues.getString(selectValues.getColumnIndex("title")), selectValues.getString(selectValues.getColumnIndex("msg")), selectValues.getInt(selectValues.getColumnIndex("state")), selectValues.getInt(selectValues.getColumnIndex("type")), selectValues.getString(selectValues.getColumnIndex("time"))); Log.d("输出查询结果:", message.getId()+"="+message.getMid()+"="+message.getUser()+"="+ message.getTitle()+"="+message.getMsg()+"="+message.getState()+"="+message.getType()+"="+message.getTime()); } selectValues.close(); dbUtilsSelect.closeDB();