Android 数据存储之SQLite数据库
转载请标明出处: http://blog.csdn.net/airsaid/article/details/52419418
本文出自:周游的博客
- 前言
- SQLiteDatabase
- 创建数据库和表
- 操作数据库
- insert
- dalete
- update
- query
- 实例
- 事务
- SQLiteOpenHelper
- 方法
- 实例
前言
Android中有许多的数据存储方式,如果我们有少量的数据需要存储,那么使用:SharedPreferences、文件存储就可以了。但是如果有大量数据需要进行读写,那么就需要使用到数据库了。Android中内置了SQLite数据库,而SQLite数据库是一个真正轻量级的数据库,它并没有后台进程,整个数据库就对应于一个文件。Android也给我们提供了大量的API,使用起来很方便。
SQLiteDatabase
Android提供了SQLiteDatabase对象来管理数据库,SQLiteDatabase有提供方法来创建,删除,执行SQL命令,并执行常见的数据库管理任务。
SQLiteDatabase提供了如下静态方法来打开一个文件对应的数据库:
- SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags):
打开path文件所代表的SQLite数据库。 - SQLiteDatabase openOrCreateDatabase(File file, SQLiteDatabase.CursorFactory factory):
打开或创建(如果不存在)file文件所代表的SQLite数据库。 - SQLiteDatabase openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory):
打开或创建(如果不存在)path文件所代表的SQLite数据库。
当我们获取到SQLiteDatabase对象之后,就可以调用SQLiteDatabase如下的方法来对数据库进行操作了:
JAVA方法 | 释义 |
---|---|
execSQL(String sql) | 执行SQL语句 |
execSQL(String sql, Object[] bindArgs) | 执行带占位符的SQL语句 |
insert(String table, String nullColumnHack, ContentValues values) | 向指定表中插入特定数据 |
delete(String table, String whereClause, String[] whereArgs) | 删除指定表中的特定数据 |
update(String table, ContentValues values, String whereClause, String[] whereArgs) | 更新指定表中的数据 |
query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,String having, String orderBy) | 查询执行表中的数据 |
query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,String having, String orderBy, String limit) | 查询执行表中的数据,limit参数控制最多查询几条数据 |
query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs,String groupBy, String having, String orderBy, String limit) | 查询执行表中的数据,distinct 参数表示是否去除重复的值 |
rawQuery(String sql, String[] selectionArgs) | 执行带占位符的SQL语句查询 |
beginTransaction() | 开始事务 |
endTransaction() | 结束事务 |
Android提供了上面的方法,来帮助开发者更“简便”的对数据库进行增删改查。但是其实这些方法完全可以通过SQL语句来完成。而用记上面复杂的参数的时间,就可以来掌握SQL语句了。
上面的方法,都是返回了一个Cursor接口,该接口提供对由数据库查询返回的结果集的随机读写访问,而Cursor同样提供了如下方法来移动查询结果的记录指针:
JAVA方法 | 释义 |
---|---|
move(int offset) | 从当前位置向前或向后移动记录指针,如果移动成功则返回true |
moveToFirst() | 移动记录指针到第一行 |
moveToLast() | 移动记录指针到最后一行 |
moveToNext() | 移动记录指针到下一行 |
moveToPrevious() | 移动记录指针到上一行 |
moveToPosition(int position) | 移动记录指针到指定行 |
isFirst() | 是否指向第一条 |
isLast() | 是否指向最后一条 |
isBeforeFirst() | 是否指向第一条之前 |
isAfterLast() | 是否指向最后一条之后 |
isNull(int columnIndex) | 指定列是否为空(列基数为0) |
isClosed() | 游标是否已关闭 |
getCount() | 总数据项数 |
getPosition() | 返回当前游标所指向的行数 |
getColumnIndex(String columnName) | 返回某列名对应的列索引值 |
getString(int columnIndex) | 返回当前行指定列的值 |
一旦通过以上方法移动到指定行后,就可以调用Cursor的getXXX()方法来获取指定列的数据了。
创建数据库和表
- 创建数据库:
// 判断数据库文件存放的文件夹是否存在,不存在则创建
String mPath = Environment.getExternalStorageDirectory() + "/db/";
File file = new File(mPath);
if(!file.exists() && !file.isDirectory()){// 创建目录file.mkdirs();
}
// 使用静态方法打开数据库(不存在则创建),第二个参数用于返回Course工厂,null则表示使用默认工厂。
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(mPath + "blog.db", null);
- 创建表:
// 执行创建表SQL语句,创建了一个名为blog_info的表
String createSql = "create table blog_info(blog_id integer primary key, blog_name varchar(255), blog_link varchar(255))";
database.execSQL(createSql);
注意:由于数据库创建在SD卡中,所以需要加上写入SD卡权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
操作数据库
在创建好数据库和表之后就可以对表中的数据进行管理和操作了。我们可以直接通过execSQL()方法执行SQL语句来操作,也可以使用Android给我们直接提供的增删改查方法。
insert
- insert(String table, String nullColumnHack, ContentValues values):
- table:想插入数据的表名。
- nullColumnHack:代表强行charunull值的数据列列名。当values参数为null或不想包含任何key-value对时该参数有效。
- values:代表一行记录的数据。
插入的数据参数为ContentValues,ContentValues有点类似与Map集合,它也有put(String key, XXX value)方法,其中key为数据列名,getXxx(String key)为取出对应列名的数据。
往刚刚上面创建的数据库blog_info表中插入一条数据:
ContentValues contentValues = new ContentValues();
contentValues.put("blog_name", "Airsaid");
contentValues.put("blog_link", "http://blog.csdn.net/airsaid");
// line为新添加的行号,该行号是一个内部值,与主键id无关,当发生错误时,返回-1。
long line = mDatabase.insert("blog_info", null, contentValues);
dalete
- delete(String table, String whereClause, String[] whereArgs):
- table:代表想删除数据的表名。
- whereClause:满足该whereClause子句的记录将会被删除。
- whereArgs:用于为whereClause子句传入参数。
删除和”Airsaid”相关的数据:
int num = mDatabase.delete("blog_info", "blog_name like ?", new String[]{"Airsaid"});
Toast.makeText(this, "一共删除了:" + num + "条数据", Toast.LENGTH_SHORT).show();
update
- update(String table, ContentValues values, String whereClause, String[] whereArgs):
- table:代表需要更新的表名。
- values:代表想更新的数据。
- whereClause:满足该WhereClause子句的数据将会被更新。
- whereArgs: 用于为whereClause子句传入参数。
将所有主键大于5的blog_name改为周游:
ContentValues contentValues = new ContentValues();
contentValues.put("blog_name", "周游");
int num = mDatabase.update("blog_info", contentValues, "_id > ?", new String[]{"5"});
query
- query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs,String groupBy, String having, String orderBy, String limit):
- distinct:是否去除重复记录。
- table:需要执行查询的表名。
- columns:要查询出来的列名。
- selection:查询条件子句。
- selectionArgs:占位符传入参数。
- groupBy:用与控制分组。
- having:用于对分组进行排序。
- orderBy:用于对记录进行排序。
- limit:用于进行分页。
由于查询条件的不确定性,所以query()方法的参数真的是比较长。。感觉建议在写查询语句的时候,可以直接使用rawQuery()方法进行查询。
实例
下面写一个实例,用户分别输入博客名和博客链接,点插入后,将数据存储到数据库,并用列表展示出来:
* 布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.airsaid.sqlitedemo.MainActivity"><EditText
android:id="@+id/edt_blog_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"/><EditText
android:id="@+id/edt_blog_link"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"/><Button
android:onClick="insert"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="插入数据"/><ListView
android:id="@+id/listView"android:layout_marginTop="10dp"android:layout_width="match_parent"android:layout_height="wrap_content"/>
</LinearLayout>
- 代码:
public class MainActivity extends AppCompatActivity {private String mPath = Environment.getExternalStorageDirectory() + "/db/";private static final String DB_NAME = "blog.db";private EditText mEdtName;private EditText mEdtLink;private ListView mListView;private SQLiteDatabase mDatabase;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mEdtName = (EditText) findViewById(R.id.edt_blog_name);mEdtLink = (EditText) findViewById(R.id.edt_blog_link);mListView = (ListView) findViewById(R.id.listView);// 判断数据库文件存放的文件夹是否存在,不存在则创建File file = new File(mPath);if(!file.exists() && !file.isDirectory()){// 创建目录file.mkdirs();}// 使用静态方法打开数据库(不存在则创建),第二个参数用于返回Course工厂,null则表示使用默认工厂。mDatabase = SQLiteDatabase.openOrCreateDatabase(mPath + DB_NAME, null);// 执行创建表SQL语句,创建了一个名为blog_info的表String createSql = "create table blog_info(_id integer primary key, blog_name varchar(255), blog_link varchar(255))";mDatabase.execSQL(createSql);}/*** 插入数据*/public void insert(View v){// 获取用户输入信息String name = mEdtName.getText().toString();String link = mEdtLink.getText().toString();// 执行SQL语句插入数据mDatabase.execSQL("insert into blog_info values(null, ?, ?)", new String[]{name, link});// 填充数据到ListViewCursor cursor = mDatabase.rawQuery("select * from blog_info", null);SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_listview_blog, cursor, new String[]{"blog_name", "blog_link"}, new int[]{R.id.txt_name, R.id.txt_link}, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);mListView.setAdapter(adapter);}
}
- Item布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center"android:orientation="horizontal"><TextView
android:id="@+id/txt_name"android:layout_width="0dp"android:layout_height="50dp"android:layout_weight="1"/><TextView
android:id="@+id/txt_link"android:layout_width="0dp"android:layout_height="50dp"android:layout_weight="1"/></LinearLayout>
运行结果:
事务
数据库操作,事务是少不了的,而SQLiteDatabase也提供了如下几个方法来操作事务:
* beginTransaction():开始事务。
* endTransaction():结束事务。
* inTransaction():判断当前上下文是否处于事务中。
当调用endTransaction()方法结束事务的时候,那么到底是提交事务还是进行回滚事务呢?这取决于SQLiteDatabase是否调用了:setTransactionSuccessful()方法来设置事务标志,如果在执行事务的时设置了,当事务成功则提交事务,否则程序将回滚事务。
SQLiteOpenHelper
其实在真实项目开发中,很少使用SQLiteDatabase的方法来打开数据库,而是通过继承Android给我们提供的SQLiteOpenHelper抽象类来创建。
SQLiteOpenHelper是一个辅助类,用于来帮助我们建立和管理数据库。我们只需要继承它,并实现两个抽象方法:
* onCreate(SQLiteDatabase db):在初次生成数据库的时候会被调用,用于生成表结构。
* onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):在数据库版本发生更新时会被调用,oldVersion为旧数据库版本号,newVersion为新版本数据库版本号。
方法
SQLiteOpenHelper有如下方法:
JAVA方法 | 释义 |
---|---|
getWritableDatabase() | 以写的方式打开数据库对应的SQLiteDatabase对象 |
getReadableDatabase() | 以读写的方式打开数据库对应的SQLiteDatabase对象 |
getDatabaseName() | 返回被打开SQLite数据库的名称 |
onConfigure(SQLiteDatabase db) | 正在配置数据库连接时调用 |
onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) | 当数据库降级时调用 |
onOpen(SQLiteDatabase db) | 当数据库已经打开时调用 |
setWriteAheadLoggingEnabled(boolean enabled) | 启用或者禁用数据库中使用预写日记记录 |
实例
- 继承SQLiteOpenHelper,在onCreate方法中创建数据库表:
public class MyDatabaseHelper extends SQLiteOpenHelper {public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {// 创建表结构db.execSQL("create table dict(_id integer primary key autoincrement, word, detail)");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
- 布局很简单,分别为单词输入框和释义输入框,输入完成后点击按钮保存到数据库,保存数据后,用户可以输入要查询的生词进行查询,点击查询将结果作为dialog展示出来。添加生词的方法如下:
public void add(View v) {// 添加生词String word = mEdtWord.getText().toString();String detail = mEdtDetail.getText().toString();if(TextUtils.isEmpty(word) || TextUtils.isEmpty(detail)){Toast.makeText(this, "输入的数据不能为空", Toast.LENGTH_SHORT).show();return;}SQLiteDatabase database = mDb.getReadableDatabase();database.execSQL("insert into dict values(null, ? , ?)", new String[]{word, detail});Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();
}
主要是通过SQLiteOpenHelper的 getReadableDatabase()方法获取了SQLiteDatabase对象。这里需要注意的是:
getReadableDatabase()方法会先以读写方式打开数据库,如果数据库的磁盘空间已经满了,那么就会打开失败,然后再尝试以只读的方式打开数据库。
而通过getWritableDatabase()方法,如果磁盘空间已满,打开时就会出错。
- 查询:
public void seek(View v) {// 查看生词String dict = mEdtInput.getText().toString();SQLiteDatabase database = mDb.getReadableDatabase();Cursor cursor = database.rawQuery("select * from dict where word like ? or detail like ?", new String[]{"%" + dict + "%", "%" + dict + "%"});List<String> dicts = new ArrayList<>();while (cursor.moveToNext()){String word = cursor.getString(1);String detail = cursor.getString(2);dicts.add("生词:" + word + " 解释:" + detail);}showData(dicts);
}
- 将结果展示:
private void showData(List<String> dicts) {if(dicts.size() < 1) {Toast.makeText(this, "没有找到到该生词数据", Toast.LENGTH_SHORT).show();return;}String[] strings = dicts.toArray(new String[dicts.size()]);for (String string : strings) {Log.e("test", string);}new AlertDialog.Builder(this).setTitle("查询出来的单词结果").setItems(dicts.toArray(new String[dicts.size()]), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}}).create().show();
}
运行结果:
参考文章:《疯狂Android讲义》
Android 数据存储之SQLite数据库相关推荐
- 安卓 sqlite数据存入mysql_详解Android数据存储—使用SQLite数据库
SQLite是Android自带的关系型数据库,是一个基于文件的轻量级数据库.Android提供了3种操作数据的方式,SharedPreference(共享首选项).文件存储以及SQLite数据库. ...
- Android数据存储之SQLite数据库存储
Android中每一个数据库对创建它的应用程序包套件来说都是私有的,默认情况下其他应用程序无法直接访问此私有数据库.所有的数据库文件存放在手机中的/data/data/package_name/dat ...
- 数据存储之 SQLite 数据库操作(三)
上一讲中我们讲到了SQLite数据库的操作方法 [数据存储之SQLite数据库操作(二)],我们主要是以SQL语句对数据库进行增删改查,这一讲我们来学习一下 Android 建议的对数据库的操作方法 ...
- 数据存储之 SQLite 数据库操作(二)
上一讲我们讲解了SQLite数据库的创建[数据存储之 SQLite 数据库操作(一)],还有更新的操作,这一讲我们来讲解一下数据库的增删改查,这边的程序是对上一个程序进行修改,建议结合上一讲内容进行学 ...
- 数据存储之 SQLite 数据库操作(一)
这一讲我们来讲解一下数据库的存储方式 ,SQLite数据库属于文本型的数据库,它是以文本的形式来保存的. 1. SQLite 数据库介绍 查看 Android API文档中 SQLite 的介绍 ...
- Android数据存储之SQLite的操作
Android作为一个应用在移动设备上的操作系统,自然也就少不了数据的存储.然而SQLite作为一个轻型的关系型数据库,基于其轻量.跨平台.多语言接口及安全性等诸多因数考虑,因而Android较大的数 ...
- 数据存储之-SQLite数据库一
概述 SQLite是一个轻量级的关系型数据库,运算速度快,占用资源少,很适合在移动设备上使用, 不仅支持标准SQL语法,还遵循ACID(数据库事务)原则,无需账号,使用起来非常方便! SQLite支持 ...
- Android持久化存储(3)SQLite数据库的使用
1.什么是SQlite SQLite是由C语言编写的一款轻型数据库,因占用资源小,处理速度快,功能齐全,特别适用于移动设备,最重要的是开源,任何人都可以使用它,许多开源项目(PHP,Python)和当 ...
- Android数据存储之SQLite
概览 l 概述 l CRUD方法详解 l 注意事项 概述 对于大量数据的处理,如果不想将数据存于服务器端,Android API提供了对关系数据库SQLite的支持,在android-SD ...
最新文章
- oracle11g 启动报错 缺少系统参数
- centos7 python3.7 ssl_centos6.8安装python3.7无法import _ssl的解决方法
- Git复习(十二)之命令专场
- java中属性外部化_用Java可外部化
- lib60870-IEC 60870-5-101 / 104 协议对总查询的处理
- 安装Vuecli新版本正常,但是显示版本是低版本
- 服务器zip解压php,服务器端解压缩zip的脚本
- Pyplot绘图的格式
- 代码 微信小程序 词典_微信小程序+ANKIWEB-学习语言的神器,背诵单词的利剑
- python从入门到精通 明日科技 电子书-Python从入门到精通(明日科技出版) 源代码+课件+视频 全套...
- 梯度下降法,最速下降法,牛顿法,Levenberg-Marquardt 修正,共轭方向法,共轭梯度法
- Ubuntu:conda的安装与使用
- python3.7帮助文档,文档说明 · Python3.7.3官方文档 简体中文 · 看云
- loadrunner压力测试一般使用流程
- Python:Dir及str函数
- 对 input 千位分割
- GOCI数据批量下载
- linux串口特殊字符不能接收
- openGL,glut库安装(vs2013)
- word2016中公式不能用斜体的解决方法
热门文章
- 计算机视觉-CS231n-Lecture 1
- Vue.js入门学习--列表渲染--v-for遍历数组生成元素(四)
- linux删除用户失败:userdel:user xxx is currently used by process xxxx
- 转自BMY 海量数据的处理
- 蓝桥杯-方格计数(java)
- python实现鱼眼图与六面图的转换
- 电子政务外网平台建设
- Ubuntu 16.04 如何安装Fcitx五笔拼音输入法
- 分享一个ubuntu18.04(20.04)的MacOS美化主题和下载,作者很用心也写得很详细。
- spring security_一文肝爆Spring安全框架Spring Security