Android SQLiteDatabase
来源:互联网 发布:交通组织优化方案 编辑:程序博客网 时间:2024/05/21 06:34
Android - SQLite数据库
程序中使用数据库,通常是:
- 设计表结构
- 需要哪些表
- 表之间的关系
- 有哪些字段
- …
- 创建数据库
- 数据库名称
- 存储路径
- 文件大小
- …
- 创建表
- 字段相关内容
- 业务相关 (根据不同的需求,可选)
- 视图
- 存储过程
- 函数
- …
那下面来看下我们Android中数据库的操作,更多内容请看:SQLite文档
设计表结构 (Contract)
程序中需要哪些表,有哪些列(字段,属性),表之间的关系…
以前写Java程序时是通过写JavaBean类,在bean包下创建很多个实体类,在Android中,Google建议我们使用 Contract(契约类)
契约类 :是用于定义 URI、表格和列名称的常数的容器
项目经验很少,并不是很懂写契约类,和那些实体类相比有什么大大的优势,只是在结合ContentProvider时,契约类更能派上用场,好吧,留待以后慢慢体会,接着写…
我们简单的写一个学生信息(Student)的增删改查(CRUD)好了
看下契约类长什么样子
~~~
// 定义学生管理系统的契约类
public final class StudentContract {
// 私有化构造器,避免创建对象,因为我们不用该类对象
private StudentContract() {}
// 定义Student表内容的内部类public static class StudentEntry implements BaseColumns { public static final String TABLE_NAME = "student"; public static final String COLUMN_STU_NAME = "stuName"; public static final String COLUMN_STU_AGE = "stuAge";}
}
~~~
这里我们只使用了一张表,如果有多张表,那么就在契约类中添加定义表内容的内部类,就像StudentEntry类一样。
看到我们的 StudentEntry 类实现了 BaseColumns 接口,BaseColumns接口中只有两个字段,一个是 _ID ,另一个是 _COUNT,也就是说StudentEntry设计的表有5列。其中_ID那一列作为主键。
以上就是定义表结构,其实就是定义几张不同的表,它有哪些列。最后看下我们上述实现的表的图示。
创建数据库 (SQLiteOpenHelper)
表的结构定义完成,那我们是不是按照契约创建数据库,创建表了?答案是肯定的。
创建数据库,必然少不了操作数据库的类,Android中给我们提供了SQLiteDatabase 类来进行数据库的相关操作,我们要创建数据库,来看下API,有没有创建数据库的方法。
嘿,找到了 create() ,看下方法的文档说明,咦,当数据库关闭时,数据库内容就被销毁了???(关于create方法,里面有一个In-Memory Database的概念,感兴趣的同学可以去了解下),HAi,这方法不行啊。
接着看API….,哈哈,不看了
好吧,不卖关子了,其实所有的创建数据库的方法(create()、openDatabase(重载)、openOrCreateDatabase(重载)),最终都会执行openDatabase(String path,CursorFactory factory, int flags,DatabaseErrorHandler errorHandler)
看下它是怎么创建
public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,DatabaseErrorHandler errorHandler) { SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler); db.open(); return db; }
嘿呀,流了一大把汗终于把数据库new出来了,哎,下面db.open(),打开数据库?是的,我们的数据库并不是new出来就能增删改查的,它要创建并且打开后才能使用它进行CRUD操作的。
数据库创建
path : 数据库创建了,保存的路径,这个路径包含数据库的名称吧,假如我们没有给数据库起名字?是不是很嗨?后面我们使用SQLiteOpenHelper时,会有这个参数,假如传递null,即不给它起名字,那么它便会创建一个”In-Memory Database” ,这里是 In-Memory Databases文档
flags : 这里会有打开的方式(只读 or 读写),假如我们以只读的方法打开了,那么我们只能查询,怎么增删改呢?那就以全以读写的方式打开啊,那我们的数据库部分内容只有有权限的人进行增删改呢,那就让它以只读方法打开啊。嘿,就一个打开就这么麻烦的吗?
数据库更新
业务需求的变更,数据库的表结构可能也要有相应的更改,那数据库的更新该怎么做呢?向上升级,向下降级
升级或者降级,需要备份当前数据库后删除,然后导入新的数据库中,删除和导入的过程中出现了问题怎么办?还要使用数据库事务,开启事务,删除,导入,关闭事务。
据上所述,数据库的创建,和版本更新是一个比较复杂的事情,因此Google给我们提供了一个便于数据库创建和版本更新的辅助工具类 SQLiteOpenHelper ,查看文档,我们会发现它不仅在创建和版本更新上有优势,在和ContentProvider结合使用时还有它别的优势。
其实在初学时,我们并不会有那么复杂的业务,就一个简单增删改查的方法调用,直接一个openOrCreateDatabase()就可以了啊,因此SQLiteOpenHelper的使用不是必须的,但是,它又是必须的,因为我们不会一直是初学者。养成良好的编程风格。
SQLiteOpenHelper是一个辅助类,用于方便我们数据库的创建和更新,还有一个,数据库的创建通常会保存在SDCard中,因此我们自己也可以写一个SQLiteOpenHelper,其中封装一些操作SDCard路径的内容等等类似的SQLiteHelper。
上面说了一些关于我对为何使用SQLiteOpenHelper的理解。下面来看下SQLiteOpenHelper的使用吧。
public class DbHelper extends SQLiteOpenHelper { private static DbHelper sInstance; //单例设计模式,确保程序中只有一个Database实例对象,避免Leak错误 public static synchronized DbHelper getInstance(Context context) { if (sInstance == null) { sInstance = new DbHelper(context.getApplicationContext()); } return sInstance; } private static final String DATABASE_NAME = "student.db"; private static final int DATABASE_VERSION = 1; // 私有化DbHelper类构造器,只通过getInstance方法获取DbHelper实例 private DbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } // 创建数据库 @Override public void onCreate(SQLiteDatabase db) { } // 更新数据库 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }}
嗯,大概的样子有了,结合我们的实例,学生信息管理开看下,具体的Helper中该添加哪些内容吧。
数据库操作
- 添加创建和删除的表的SQL语句
public class DbHelper extends SQLiteOpenHelper { ...... // 创建student表的sql语句 private static final String SQL_CREATE_TABLE_STUDENT = "CREATE TABLE " + StudentContract.StudentEntry.TABLE_NAME + " (" + StudentContract.StudentEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + StudentContract.StudentEntry.COLUMN_STU_NAME + " TEXT NOT NULL, " + StudentContract.StudentEntry.COLUMN_STU_AGE + " INTEGER" + ");"; // 删除student表的sql语句 private static final String SQL_DELETE_TABLE_STUDENT = "DROP TABLE IF EXISTS " + StudentContract.StudentEntry.TABLE_NAME; ...... }
- 再看onCreate()和onUpdate()方法中怎么写
public class DbHelper extends SQLiteOpenHelper { ...... // 创建数据库 @Override public void onCreate(SQLiteDatabase db) { // 执行创建语句 db.execSQL(SQL_CREATE_TABLE_STUDENT); } // 更新数据库 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //执行删除语句 db.execSQL(SQL_DELETE_TABLE_STUDENT); //重新创建表 onCreate(db); }}
这里只是给出了简单的Helper怎么写,那么具体的我们可以参考Google的代码,这里有个Google I/O 2016官方APP的源码,我们可以去看看大厂是如何写Helper的:ScheduleDatabase类 ,参考并学习它是如何创建和实现版本更新的。
哈,创建数据库写了太多内容了,下面简单写下SQLiteDatabase的C(create)、R(retrieve)、U(update)、D(delete)数据操作的方法好了(因为,网上一大把关于SQLiteDatabase的CRUD操作的文章)。
为了功能分离,我单独创建了一个StudentDb类来是先数据的增删改查
public class StudentDb { // Database由DbHelper来创建,因此需要添加依赖 private DbHelper mDbHelper; public StudentDb(DbHelper dbHelper) { mDbHelper = dbHelper; } //添加 public long insert(){ return 0; } //删除 public void delete(){ } //修改 public int update(){ return 0; } //查找 public Cursor select(String name){ return null; }}
- C_添加数据 (create)
public long insert(String name, int age) { // 获取数据库对象 SQLiteDatabase db = mDbHelper.getWritableDatabase(); // 用ContentValues装载要保存的数据 ContentValues values = new ContentValues(); values.put(StudentContract.StudentEntry.COLUMN_STU_NAME, name); values.put(StudentContract.StudentEntry.COLUMN_STU_AGE, age); // 插入数据 return db.insert(StudentContract.StudentEntry.TABLE_NAME, null, values); }
这里是参数用String name ,int age,当字段很多时呢?我们可以在别处封装数据,传递ContentValues参数就行了。
- R_查询数据(retrieve)
public Cursor select(String name) { // 获取数据库对象 SQLiteDatabase db = mDbHelper.getReadableDatabase(); // 要查询的列 String[] projection = { StudentContract.StudentEntry._ID, StudentContract.StudentEntry.COLUMN_STU_NAME, StudentContract.StudentEntry.COLUMN_STU_AGE}; // 查询条件 String selection = StudentContract.StudentEntry.COLUMN_STU_NAME + " = ?"; String[] selectionArgs = {name}; // 排序条件 String sortOrder = StudentContract.StudentEntry.COLUMN_STU_AGE + " DESC"; return db.query( StudentContract.StudentEntry.TABLE_NAME, // 要查询的表名称 projection, // 要查询的列 selection, // 查询条件列 selectionArgs, // 查询条件值 null, // 不使用group by null, // 不使用having sortOrder // 分组条件 ); }
要查询的列,如果全都查询的话,直接输入null,没有查询条件的话也是输入null。
- U_更新数据(udpate)
public int update(String oldName, String newName) { // 获取数据库对象 SQLiteDatabase db = mDbHelper.getReadableDatabase(); // 新数据 ContentValues values = new ContentValues(); values.put(StudentContract.StudentEntry.COLUMN_STU_NAME, newName); // 更新记录的过滤条件 String selection = StudentContract.StudentEntry.COLUMN_STU_NAME + " LIKE ?"; String[] selectionArgs = {oldName}; //更新 return db.update( StudentContract.StudentEntry.TABLE_NAME, values, selection, selectionArgs); }
- D_删除数据(delete)
public int delete(String name) { // 获取数据库对象 SQLiteDatabase db = mDbHelper.getWritableDatabase(); // 删除记录的过滤条件 String selection = StudentContract.StudentEntry.COLUMN_STU_NAME + " LIKE ?"; String[] selectionArgs = {name}; // 删除 return db.delete( StudentContract.StudentEntry.TABLE_NAME, selection, selectionArgs); }
由上可以看出
当进行查找,数据库中数据不发生变化时,使用helper的getReadableDatabase()方法
当进行增删改,数据发生变化时,我们使用helper的getWritableDatabase()方法
使用已经封装好了的query()方法似乎参数太多,不太好用,再加上爱装逼的我们,使用SQL脚本多好呐。哈哈,好吧,开个玩笑,Google为我们不仅仅提供这种便捷的方法,还提供了一种通用的execSQL()方法,另外还有单门执行select语句的rawQuery()方法。呐,具体用哪个看个人的喜好还有哪个更方便操作了。
至此,关于Android SQLite数据库的内容就结束了,感谢您的阅读。
如果你对我的文章感兴趣,欢迎关注我的微信公众号: oogh ,期待你的到来
- Android-SQLitedatabase
- Android SQLiteDatabase
- Android SQLiteDatabase
- Android:SQLiteOpenHelper,SqliteDatabase学习
- android SQLiteDatabase之一
- Android SQLiteDatabase的使用
- android Sqlitedatabase 应用
- [android]数据库SQLiteDatabase简介
- Android:Sqlitedatabase学习小结
- 【Android基础 001】 sqlitedatabase
- Android SQLiteDatabase query语句
- Android sqlitedatabase 事务
- android SQLiteDatabase详解
- Android SQLiteDatabase分析
- Android 数据库SQLiteDatabase
- Android:Sqlitedatabase学习小结
- android SQLiteDatabase之一
- android下删除sqlitedatabase
- 安装bochs debugger GUI
- 迁移学习系列(一)
- 关于HBase的几个问答。
- C++ 关键字
- 类成员的访问权限与继承权限
- Android SQLiteDatabase
- Android之JNI DETECTED ERROR IN APPLICATION: illegal class name 'XXX'的错误解决方法
- Zabbix编译安装过程中遇到的问题
- Python for Eclipse
- webxml引申来的
- Struts2.5+eclipse+tomcat8.5配置
- 滚动RecyclerView加载图片时的流畅度优化
- 支付宝的RSA加签验签机制
- 【基础JSP 练习】