Android学习笔记034之数据存储SQLite数据库.docx
- 文档编号:27976605
- 上传时间:2023-07-07
- 格式:DOCX
- 页数:14
- 大小:30.49KB
Android学习笔记034之数据存储SQLite数据库.docx
《Android学习笔记034之数据存储SQLite数据库.docx》由会员分享,可在线阅读,更多相关《Android学习笔记034之数据存储SQLite数据库.docx(14页珍藏版)》请在冰豆网上搜索。
Android学习笔记034之数据存储SQLite数据库
Android学习笔记034之数据存储—SQLite数据库
前面我们介绍了Android数据存储的两种方法:
文件存储和SharedPreference存储,这一篇我们来学习一下Android存储数据的另外一种方式——SQLite数据库存储。
1、SQlite数据库简介
现在的主流移动智能设备中,比如Android手机、iPhone手机,平板等都是使用SQLite数据库作为存储复杂数据的存储引擎。
那么什么是SQLite数据库呢?
SQLite是D.RichardHipp用C语言编写的开源嵌入式数据库引擎,它支持大多数的SQL92标准,并且可以在所有主要的操作系统上运行。
SQLite由以下几个部分组成:
SQL编译器、内核、后端以及附件。
SQLite通过利用虚拟机和虚拟数据库引擎(VDBE),是调试、修改和扩展SQLite的内核变得更加方便。
所有SQL语句都被编译成易读的、可以在SQLite虚拟机中执行的程序集。
SQlite数据库是一个轻量级的关系型数据库,不需要像其它关系型数据库一样需要安装,Android已经将SQLite数据库内置在系统中,内置的版本是3.0版本。
SQlite支持标准的SQL语法,还支持ACID(数据库事务)原则,占用资源非常少,非常适合在移动设备中使用。
袖珍型的SQLite数据库就可以支持高达2TB大小的数据库,每个数据库都是以单个文件的形式存在,这些数据都是以B-Tree的数据结构形式存储在磁盘上。
每一个数据库是一个文件,数据库中可以包含多个表,表中可以包含多个字段。
SQLite数据库支持NULL、INTEGER、REAL、TEXT和BLOB数据类型,分别代表空值、整型值、浮点值、字符串文本、二进制对象。
SQLite采用动态数据类型,当某个值插入到数据库时,SQLite将会检查它的类型,如果该类型与关联的列不匹配,SQLite则会尝试将该值转换成该列的类型,如果不能转换,则该值将作为本身的类型存储,SQLite称这为“弱类型”。
但有一个特例,如果是INTEGERPRIMARYKEY,则其他类型不会被转换,会报一个“datatypemissmatch”的错误。
简单的说就是:
我们可以各种数据类型的数据保存到任何字段中而不用关心字段声明的数据类型。
下面是Android系统中SQLite数据库的几个关键类:
SQLiteOpenHelper:
数据库抽象类,我们通过继承该类,获取数据库实例,然后可以重写数据库创建、更新版本方法和关闭数据库
SQLiteDatabase:
数据库访问类:
我们通过获取这个类的实例来对数据库做一些CRUD操作
Cursor:
游标:
类似于JDBC里的结果集
2、SQLiteOpenHelper创建数据库与版本管理
我们继承SQLiteOpenHelper这个类的时候必须要实现两个方法:
onCreate(SQLiteDatabasesqLiteDatabase)和onUpgrade(SQLiteDatabasesqLiteDatabase,inti,inti1),onCreate方法是我们第一次使用应用的时候生成数据表;onUpgrade方法是数据库版本发生变更的时候调用。
还有必须要实现一个构造方法,下面是代码示例:
publicclassDBOpenHelperextendsSQLiteOpenHelper{
privatestaticStringDB_NAME="db_test.db";
privatestaticintDB_VERSION=1;
publicDBOpenHelper(Contextcontext){
super(context,DB_NAME,null,DB_VERSION);
}
/**
*数据库第一次创建的时候调用
*
*@paramsqLiteDatabase
*/
@Override
publicvoidonCreate(SQLiteDatabasesqLiteDatabase){
}
/**
*数据库版本发生改变的时候调用
*
*@paramsqLiteDatabase
*@parami
*@parami1
*/
@Override
publicvoidonUpgrade(SQLiteDatabasesqLiteDatabase,inti,inti1){
}
}
上述代码启动会创建一个db_test.db的数据库文件,在data/data/包名/database目录下就可以看到创建的数据库文件,将其导出之后就可以用图形化工具查看。
3、SQLite数据库图形化工具
SQLite图形化工具很多,推荐使用SQLiteexpert,这是官网下载地址。
这个图形化工具使用也很简单,直接将从AndroidDeviceMonitor导出的数据库文件导入就可以查看数据。
这个可视化工具实用不是很复杂,就不在做很多的介绍了。
4、SQLite数据库使用
下面我们进行数据库的基本使用,在Android开发中,我们不需要写很多SQL语句,Android已经帮我们封装好了,我们直接调用就可以了。
Android提供的CRUD操作的方法介绍:
数据增加:
insert(Stringtable,StringnullColumnHack,ContentValuesvalues)
参数解析:
第一个是数据表名;第二个是设置为null值的数据表名;第三个是插入的数据,用ContentValues封装。
数据删除:
delete(Stringtable,StringwhereClause,String[]whereArgs)
参数解析:
第一个是数据表名;第二个是where条件;第三个是约束
数据更新:
update(Stringtable,ContentValuesvalues,StringwhereClause,String[]whereArgs)
参数解析:
第一个是数据表名;第二个是改变的数据;第三个是where条件;第四个是约束
数据查询:
query(Stringtable,String[]columns,Stringselection,String[]selectionArgs,StringgroupBy,Stringhaving,StringorderBy,Stringlimit)
query(booleandistinct,Stringtable,String[]columns,Stringselection,String[]selectionArgs,StringgroupBy,Stringhaving,StringorderBy,Stringlimit,CancellationSignalcancellationSignal)
query(Stringtable,String[]columns,Stringselection,String[]selectionArgs,StringgroupBy,Stringhaving,StringorderBy)
query(booleandistinct,Stringtable,String[]columns,Stringselection,String[]selectionArgs,StringgroupBy,Stringhaving,StringorderBy,Stringlimit)
参数解析:
table:
表名称
colums:
表示要查询的列所有名称集
selection:
表示WHERE之后的条件语句,可以使用占位符
selectionArgs:
条件语句的参数数组
groupBy:
指定分组的列名
having:
指定分组条件,配合groupBy使用
orderBy:
y指定排序的列名
limit:
指定分页参数
distinct:
指定“true”或“false”表示要不要过滤重复值
Cursor:
返回值,相当于结果集ResultSet
下面通过实现数据库的基本CRUD操作体会一下:
Activity代码:
packagecom.example.datasave;
importandroid.content.ContentValues;
importandroid.database.Cursor;
importandroid.database.sqlite.SQLiteDatabase;
importandroid.os.Bundle;
importandroid.support.annotation.Nullable;
importandroid.support.v7.app.AppCompatActivity;
importandroid.util.Log;
importandroid.view.View;
importandroid.widget.Button;
importjava.util.ArrayList;
importjava.util.List;
/**
*CreatedbyDevinon2016/7/20.
*/
publicclassSQLiteActivityextendsAppCompatActivity{
privateButtonbtn_sqlite_insert;
privateButtonbtn_sqlite_delete;
privateButtonbtn_sqlite_update;
privateButtonbtn_sqlite_select;
privateSQLiteDatabasemDatabase;
privateDBOpenHelpermDBOpenHelper;
privatestaticfinalStringTAG="SQLiteActivity";
@Override
protectedvoidonCreate(@NullableBundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite);
mDBOpenHelper=newDBOpenHelper(this);
mDatabase=mDBOpenHelper.getWritableDatabase();
btn_sqlite_insert=(Button)findViewById(R.id.btn_sqlite_insert);
btn_sqlite_insert.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewview){
insert();
}
});
btn_sqlite_delete=(Button)findViewById(R.id.btn_sqlite_delete);
btn_sqlite_delete.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewview){
delete(5);
}
});
btn_sqlite_update=(Button)findViewById(R.id.btn_sqlite_update);
btn_sqlite_update.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewview){
update(6);
}
});
btn_sqlite_select=(Button)findViewById(R.id.btn_sqlite_select);
btn_sqlite_select.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewview){
select();
}
});
}
privatevoidselect(){
Cursorcursor=mDatabase.query("student",null,null,null,null,null,null);
List
while(cursor.moveToNext()){
StudentModelmodel=newStudentModel();
model.setS_id(cursor.getInt(cursor.getColumnIndex("s_id")));
model.setName(cursor.getString(cursor.getColumnIndex("name")));
model.setSex(cursor.getString(cursor.getColumnIndex("sex")));
model.setGrade(cursor.getString(cursor.getColumnIndex("grade")));
students.add(model);
Log.i(TAG,"数据---->>"+model.toString());
}
cursor.close();
ToastUtils.showToast(this,students.toString());
}
privatevoidupdate(ints_id){
ContentValuesvalues=newContentValues();
values.put("ade","2013级信计班");
mDatabase.update("student",values,"s_id=?
",newString[]{""+s_id+""});
ToastUtils.showToast(this,"更新了s_id为"+s_id+"的数据");
}
privatevoidinsert(){
ContentValuesvalues=newContentValues();
values.put("name","李四");
values.put("sex","男");
values.put("grade","2012级数应班");
mDatabase.insert("student",null,values);
ToastUtils.showToast(this,"插入数据成功");
}
privatevoiddelete(intposition){
mDatabase.delete("student","s_id=?
",newString[]{""+position+""});
ToastUtils.showToast(this,"删除了s_id为"+position+"的数据");
}
}
SQLiteOpenHelper代码:
packagecom.example.datasave;
importandroid.content.Context;
importandroid.database.sqlite.SQLiteDatabase;
importandroid.database.sqlite.SQLiteOpenHelper;
/**
*CreatedbyDevinon2016/7/20.
*/
publicclassDBOpenHelperextendsSQLiteOpenHelper{
privatestaticStringDB_NAME="db_test.db";
privatestaticintDB_VERSION=1;
privatestaticfinalStringTEST_TABLE="CREATETABLEstudent(s_idINTEGERPRIMARYKEYAUTOINCREMENT,"+
"nameVARCHAR(20),sexVARCHAR(10),gradeVARCHAR(100))";
publicDBOpenHelper(Contextcontext){
super(context,DB_NAME,null,DB_VERSION);
}
/**
*数据库第一次创建的时候调用
*
*@paramsqLiteDatabase
*/
@Override
publicvoidonCreate(SQLiteDatabasesqLiteDatabase){
sqLiteDatabase.execSQL(TEST_TABLE);
}
/**
*数据库版本发生改变的时候调用
*
*@paramsqLiteDatabase
*@parami
*@parami1
*/
@Override
publicvoidonUpgrade(SQLiteDatabasesqLiteDatabase,inti,inti1){
}
}
布局文件非常简单,就不再贴代码了,下面是实现效果图:
由于是录制GIF,速度比较慢,这样就可以基本实现数据库的CRUD操作。
5、SQLite数据库事务
上面我们介绍了SQLite的基本操作,现在我们来介绍一下SQLite数据库的事务,首先,来了解一下什么是事务?
什么是事务?
数据事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
简单的说,就是多个操作捆绑到一起执行,只有所有的操作都成功了,事务才算执行完毕,才会提交,只要有一个操作没有完成,事务都会回滚,所有的操作都不回提交。
举一个例子就是:
张三向李四转账1000块,张三的账户上要减少1000块,李四的账户上要增加1000块,只有两个操作都完成,事务才会提交。
假如张三的账户减少了1000块,但是李四的账户上没有增加1000块;或者张三的账户没有减少1000块,但是李四的账户增加了1000块,这显然都是不可以的。
比如下面的例子代码:
/**
*事务测试
*/
publicvoidpayment(){
SQLiteDatabasedb=mDBOpenHelper.getWritableDatabase();
//开启事务
db.beginTransaction();
try{
db.execSQL("updatepersonsetamount=amount-10wherepersonid=?
",newObject[]{1});
db.execSQL("updatepersonsetamount=amount+10wherepersonid=?
",newObject[]{2});
//设置事务标志为成功,当结束事务时就会提交事务
db.setTransactionSuccessful();
}catch(Eptione){
e.printStackTrace();
}finally{
//结束事务
db.endTransaction();
}
}
简单的说就是:
只有写在事务里的所有数据库操作都成功,事务才会提交,否则,事务回滚回原来的状态。
在data/data/<包名>/database/目录下,我们创建数据库的时候也会创建一个xxx.db-journal让数据库支持事务的临时日志文件。
6、SQLite数据库二进制大文件保存和读取
一般情况下,我们很少在数据库里面存储大文件,视频、音频、图片等我们都是保存路径,但是有些特殊情况下,我们需要将大文件保存到数据库里面,下面我们就实现一个简单的例子:
SQLiteDatabasedb=mDBService.getWritableDatabase();//得到数据库
try{
ByteArrayOutputStreambaos=newByteArrayOutputStream();
((BitmapDrawable)iv.getDrawable()).getBitmap().compress(
CompressFormat.PNG,100,baos);//压缩为PNG格式,100表示跟原图大小一样
Object[]args=newObject[]{baos.toByteArray()};
db.execSQL(INSERT_SQL,args);
baos.close();
db.close();
}catch(Exceptione){
e.printStackTrace();
}
}
//3.从数据库中取图片
publicvoidgetPhoto(){
StringSELECT_SQL="SELECTphotoFROMlauncher";
ImageViewappIcon=(ImageView)v.findViewById(R.id.appicon);//v是我在类中定义的一个view对象,跟前面保存图片一样
byte[]photo=null;
mDBService=newDBService(getContext());
SQLiteDatabasedb=mDBService.getReadableDatabase();
CursormCursor=db.rawQuery(SELECT_SQL,null);
if(mCursor!
=null){
if(mCursor.moveToFirst()){//justneedtoqueryonetime
photo=mCursor.getBlob(mCursor.getColumnIndex("photo"));//取出图片
}
}
if(mCursor!
=null){
mCursor.close();
}
db.close();
ByteArrayInputStreambais=null;
if(photo!
=null){
bais=newByteArrayInputStream(photo);
appIcon.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 学习 笔记 034 数据 存储 SQLite 数据库