本节引言:

本节学习Android数据库存储与访问的第三种方式:SQLite数据库,和其他的SQL数据库不同,我们并不需要在手机上另外安装一个数据库手机软件,Android系统已经集成了这个数据库,我们无需像使用其他数据库软件(Oracle,MSSQL,MySql等)又要安装,然后完成相关配置,又要改端口之类的!

   
 

1.基本的概念

1)SQLite是什么?为什么要用SQLite?SQLite有什么特点?

答:下面本姑娘来为大家讲解

SQLite是一个轻量级的关系型数据库,运算速度快,占用资源少,很适合在移动设备上使用,不仅支持标准的SQL语法,还遵循ACID(数据库事务)原则,无需账号,使用起来非常方便!

②使用文件与SharedPreference来保存数据,但是在很多情况下,文件不一定是有效的,如多线程并发访问是相关的;app要处理可能变化的复杂数据结构等等!比如银行的存钱和取钱,使用前两者就会显得很无力或者很繁琐,数据库的出现可以解决这种问题,而Android又给我们提供了一个这样轻量级的SQLite,为何不用呢?

③SQLite支持五种数据类型NULL,INTEGER,REAL(浮点数),TEXT(字符串文本)和BLOB(二进制对象),虽然只有五种,但是对于varchar,char等其他数据类型都是可以保存起来的,因为SQLite有个最大的特点:你可以各种数据类型的数据保存到任何字段中而不用关心字段声明的类型是什么,比如你可以在Integer类型的字段中存放字符串,当然除了声明主键INTEGER PRIMARY KEY的字段只能够存储64位整数!另外SQLite在解析CREATE TABLE语句时,会忽略CREATE TABLE语句中跟在字段名后面数据类型信息如下面语句会忽略 name字段的类型信息: CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))

小结下特点:

SQLite通过文件来保存数据库,一个文件就是一个数据库,数据库中又包含多个表格,表格里又有多条记录,每个记录由多个字段构成,每个字段有对应的值,每个值我们可以指定类型,也可以不指定类型(除主键之外)

   
 

2)几个相关的类:

我们在使用数据库时使用的三个相关的类:

  • SQLiteOpenHelper  抽象类,我们通过继承该类,然后重写数据库创建以及更新的方法,我们还可以通过该类的对象获取数据库的实例,或者关闭数据库。
  • SQLiteDatabase  数据库访问类:我们可以通过该类的对象来对数据库做一些增删改查的操作。
  • Cursor    游标,有点类似于JDBC里的resultset,结果集可以简单理解为指向数据库中某一个记录的指针。
   
 

2.使用SQLiteOpenHelper类创建数据库与版本管理

对于涉及数据库的app,我们不可能手动的去给他们创建数据库的文件,所以在第一次启动app的时候创建好数据库表;而当我们的应用进行升级需要修改数据库表的结构时,这个时候就需要对数据库表进行更新了,对于这两个操作,安卓给我们提供了SQLiteOpenHelper的两个方法,onCreate( )与onUpgrade( )来实现

方法的解析:

  • onCreate(database):首次使用软件时生成数据库表
  • onUpgrade(database,oldVersion,newVersion):在数据库版本发生变化时被调用,一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2或者其他旧版本号不同数据即可!

代码示例:

package com.nyl.activity;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; /**
* 创建数据库的帮助类
*/
public class MyDBOpenHelper extends SQLiteOpenHelper{ /**
* @param context 上下文
* @param name 数据库名
* @param factory 允许我们在查数据的时候返回一个自定义的Cursor,一般都是传入null
* @param version 表示当前数据库的版本号,可用于对数据库进行升级操作
*/
public MyDBOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version){
super(context,"my,db",null,);
} //数据库第一次创建时被调用
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE person(personid INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20))");
} //软件版本号发生改变时调用
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");
}
}

代码解析:

上述代码第一次启动应用,我们会创建这个my.db的文件,并且会执行onCreate()里的方法,创建了一个Person的表,它有两个字段,主键personId和name字段,接着如我们修改db的版本号,那么下次启动就会调用onUpgrade()里的方法,往表中在插入一个字段,另外这里是插入一个字段,所以数据不会丢失,如果是重建表的话,表中数据会全部丢失。

流程小结:

1.自定义一个类继承SQLiteOpenHelper类

2.在该类的构造方法的super中设置好要创建的数据库名,版本号

3.重写onCreate( )方法创建表结构

4.重写onUpgrade( )方法定义版本号发生改变后执行的操作

 
   

3.如何查看我们生成的db文件

在这里就不讲解,建议去看郭霖的《第一行代码——Android》按着流程图试试!

4.使用Android提供的API操作SQLite

哈哈~废话不多说,代码是最好的老师,我们直接进入实操吧.....

代码示例:

运行效果图:


实现代码

布局很简单,就四个Button.

<?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"
tools:context=".MainActivity"
android:orientation="vertical"> <Button
android:id="@+id/btn_insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="插入一条数据"/> <Button
android:id="@+id/btn_query"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查询当前表中数据"/> <Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="修改表中的一条数据"/> <Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除表中的一条数据"/> </LinearLayout>

MainActivity.java的代码:

package com.nyl.activity;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Context mContext;
private Button btn_insert;
private Button btn_query;
private Button btn_update;
private Button btn_delete;
private SQLiteDatabase db;
private MyDBOpenHelper myDBOpenHelper;
private StringBuilder sb;
private int i = ; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
myDBOpenHelper = new MyDBOpenHelper(mContext,"my.db",null,);
//获取布局的控件
bindViews();
} private void bindViews() {
btn_insert = (Button) findViewById(R.id.btn_insert);
btn_query = (Button) findViewById(R.id.btn_query);
btn_update = (Button) findViewById(R.id.btn_update);
btn_delete = (Button) findViewById(R.id.btn_delete); btn_insert.setOnClickListener(this);
btn_query.setOnClickListener(this);
btn_update.setOnClickListener(this);
btn_delete.setOnClickListener(this);
} @Override
public void onClick(View v) {
db = myDBOpenHelper.getWritableDatabase();
switch (v.getId()){
case R.id.btn_insert:
ContentValues values1 = new ContentValues();
values1.put("name","呵呵~" +i);
i++;
//参数依次是:表名,强行插入null值得数据列的列名,一行记录的数据
db.insert("person", null, values1);
Toast.makeText(mContext,"插入完毕~",Toast.LENGTH_LONG).show();
break;
case R.id.btn_query:
sb = new StringBuilder();
//参数依次是表名,列名,where约束条件,where中占位符提供具体的值,指定group by的列,进一步约束
//指定查询结果的排序方式
Cursor cursor = db.query("person", null, null, null, null, null, null);
if (cursor.moveToFirst()){
do {
int pid = cursor.getInt(cursor.getColumnIndex("personid"));
String name = cursor.getString(cursor.getColumnIndex("name"));
sb.append("id:" + pid + ":" +name + "\n");
}while (cursor.moveToNext());
}
cursor.close();
Toast.makeText(mContext,sb.toString(),Toast.LENGTH_SHORT).show();
break;
case R.id.btn_update:
ContentValues values2 = new ContentValues();
values2.put("name", "嘻嘻~");
//参数依次是表名,修改后的值,where条件,以及约束,如果不指定三四两个参数,会更改所有行
db.update("person",values2,"name=?",new String[]{"呵呵~2"});
break;
case R.id.btn_delete:
//参数依次是表名,以及where条件与约束
db.delete("person","personid = ?",new String[]{""});
break;
}
}
}

5.使用SQL语句操作数据库

当然,你可能已经学过SQL,会写相关的SQL语句,而且不想用Android提供的这些API, 你可以直接使用SQLiteDatabase给我们提供的相关方法:

  • execSQL(SQL,Object[]):使用带占位符的SQL语句,这个是执行修改数据库内容的sql语句用的
  • rawQuery(SQL,Object[]):使用带占位符的SQL查询操作 另外前面忘了介绍下Curosr这个东西以及相关属性,这里补充下: ——Cursor对象有点类似于JDBC中的ResultSet,结果集!使用差不多,提供一下方法移动查询结果的记录指针:
  • move(offset):指定向上或者向下移动的行数,整数表示向下移动;负数表示向上移动!
  • moveToFirst():指针移动到第一行,成功返回true,也说明有数据
  • moveToLast():指针移动到最后一样,成功返回true;
  • moveToNext():指针移动到下一行,成功返回true,表明还有元素!
  • moveToPrevious():移动到上一条记录
  • getCount( )获得总得数据条数
  • isFirst():是否为第一条记录
  • isLast():是否为最后一项
  • moveToPosition(int):移动到指定行

使用代码示例:

1.插入数据:

public void save(Person p)
{
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("INSERT INTO person(name,phone) values(?,?)",
new String[]{p.getName(),p.getPhone()});
}

2.删除数据:

public void delete(Integer id)
{
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("DELETE FROM person WHERE personid = ?",
new String[]{id});
}

3.修改数据:

public void update(Person p)
{
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("UPDATE person SET name = ?,phone = ? WHERE personid = ?",
new String[]{p.getName(),p.getPhone(),p.getId()});
}

4.查询数据:

public Person find(Integer id)
{
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM person WHERE personid = ?",
new String[]{id.toString()});
//存在数据才返回true
if(cursor.moveToFirst())
{
int personid = cursor.getInt(cursor.getColumnIndex("personid"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
return new Person(personid,name,phone);
}
cursor.close();
return null;
}

5.数据分页:

public List<Person> getScrollData(int offset,int maxResult)
{
List<Person> person = new ArrayList<Person>();
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM person ORDER BY personid ASC LIMIT= ?,?",
new String[]{String.valueOf(offset),String.valueOf(maxResult)});
while(cursor.moveToNext())
{
int personid = cursor.getInt(cursor.getColumnIndex("personid"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
person.add(new Person(personid,name,phone)) ;
}
cursor.close();
return person;
}

6.查询记录数:

public long getCount()
{
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT COUNT (*) FROM person",null);
cursor.moveToFirst();
long result = cursor.getLong();
cursor.close();
return result;
}

PS:除了上面获取条数的方法外还可以使用cursor.getCount()方法获得数据的条数, 但是SQL语句要改改!比如SELECT * FROM person;

本节小结:

本节主要是跟大家一起学习了Android内置SQLite的基本用法,下节再研究SQLite事务,应用更新数据库里数据怎么处理,以及数据库存储大二进制文件 的方法!好的,本节就到这里~晚安!

数据存储与访问之——初见SQLite数据库的更多相关文章

  1. 安卓数据存储(3):SQLite数据库存储

    SQLite简介 Google为Andriod的较大的数据处理提供了SQLite,他在数据存储.管理.维护等各方面都相当出色,功能也非常的强大.SQLite具备下列特点: 1.轻量级:使用 SQLit ...

  2. C#访问加密的SQLite数据库

    前提:一个项目需要存储各种密码数据,使用的嵌入式的SQLite数据库.默认的SQLite数据库是没有加密的,这样相当不安全.找呀找呀找方法... 方法: 1.使用SQLite管理器加密. 部分SQLi ...

  3. Android之数据存储----使用LoaderManager异步加载数据库

    一.各种概念: 1.Loaders: 适用于Android3.0以及更高的版本,它提供了一套在UI的主线程中异步加载数据的框架.使用Loaders可以非常简单的在Activity或者Fragment中 ...

  4. JDBC访问及操作SQLite数据库

    SQLite 是一个开源的嵌入式关系数据库,其特点是高度便携.使用方便.结构紧凑.高效.可靠. 与其他数据库管理系统不同,SQLite 的安装和运行非常简单,在大多数情况下,只要确保SQLite的二进 ...

  5. 【Android实验】 数据存储与访问sqlite

    目录 实验目的 实验要求 实验过程 功能分析: 实验结果: 实验的代码 实验总结 实验目的     分别使用sqlite3工具和Android代码的方式建立SQLite数据库.在完成建立数据库的工作后 ...

  6. 基于三层架构下的公共数据访问方法(Sqlite数据库)

    作者总结了一下,使用Winform的三层架构做窗体应用程序,在数据访问方面,有用到纯sql语句方法.参数方法.存储过程方法. 那么什么是三层架构呢? UI---存放Form窗体---(用户所关心的) ...

  7. Laravel 5.1 中 Session 数据存储、访问、删除及一次性Session实例教程

    1.Session的由来及其实现 HTTP协议是无状态的协议,同一个客户端的这次请求和上次请求是没有对应关系的.也就是说我们无法在服务器端确认两次请求是否是同一个用户所为,这为我们在一些应用场景中实现 ...

  8. 数据存储与访问之——SharedPreferences

    使用SharedPreferences(保存用户偏好参数)保存数据, 当我们的应用想要保存用户的一些偏好参数,比如是否自动登陆,是否记住账号密码,是否在Wifi下才能 联网等相关信息,如果使用数据库的 ...

  9. [Swift通天遁地]七、数据与安全-(5)高效操作SQLite数据库

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

随机推荐

  1. APP IM 之 XMPP和Jabber及选择方案

    1. 概述 IM ,InstantMessaging,即时通信. 现在,市面上有一批提供即时通信功能的公司.如:全时.云之讯(IM无语音和视频).容联云通讯(支持点对点音视频,按照消息的存储空间收费) ...

  2. delphi的ArrayList

    本文转载自Top.hand<delphi的ArrayList>   delphi可以用Classes.TList类来实现ArrayList功能.注意:add()方法存入的类型是TPoint ...

  3. iOS 错误 之 http请求

     Application Transport Security has blocked a cleartext HTTP (http://) resource load since it is ins ...

  4. php绘图-报表

    1.PHP报表的创建,通过绘图,过程 要先开启gb库, 可以使用jpgraph(绘图框架)快速制作一些图形 报表的作用:可以制作一些统计图,地形图,分布图等,还可以做验证码图片(通过在画布上加字和干扰 ...

  5. 《疯狂Java讲义》(七)---- 方法

    一 方法的参数传递机制 Java方法的参数传递方式只有一种:值传递.就是将实际参数值的副本传入方法内,而参数本身不会受到任何影响. eg. 基本类型的值传递 public class Primitiv ...

  6. jenkins用户权限配置错误,导致登录时提示:没有Overall/read权限

    jenkins用户权限配置错误,导致登录时提示:没有Overall/read权限 由于初次接触jenkins,于是在搭建好jenkins以后,想要对用户进行管理,于是乎开始在系统管理->conf ...

  7. jq操作radio,设置选中、获取选中值

    <label><inputtype="radio"name="sex"value="1">男</label&g ...

  8. Android项目实战(二十九):酒店预定日期选择

    先看需求效果图: 几个需求点: 1.显示当月以及下个月的日历 (可自行拓展更多月份) 2.首次点击选择"开始日期",再次点击选择"结束日期" (1).如果&qu ...

  9. 分析 OVS 如何实现 vlan 隔离 - 每天5分钟玩转 OpenStack(140)

    上一节我们完成了 OVS vlan 环境的搭建,当前拓扑结构如下: cirros-vm1 位于控制节点,属于 vlan100. cirros-vm2 位于计算节点,属于 vlan100. cirros ...

  10. HDU5475

    An easy problem Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...