GVKun编程网logo

Android数据存储之SQLite数据库

9

在本文中,我们将为您详细介绍Android数据存储之SQLite数据库的相关知识,此外,我们还会提供一些关于Adroid----数据存储之SQLite(1)、AndroidSQLite数据库彻底掌握数

在本文中,我们将为您详细介绍Android数据存储之SQLite数据库的相关知识,此外,我们还会提供一些关于Adroid----数据存储之SQLite(1)、Android SQLite数据库彻底掌握数据存储、android studio数据存储建立SQLite数据库实现增删查改、Android – 将敏感数据存储在sqlite数据库中的有用信息。

本文目录一览:

Android数据存储之SQLite数据库

Android数据存储之SQLite数据库

sqlite是一个小巧的嵌入式数据库,使用方便、开发简单,手机上最早由iOS运用,后来Android也采用了sqlite. sqlite的多数sql语法与Oracle 一样,下面只列出不同的地方:

  (1)建表时为避免重复操作,应加上IF NOT EXISTS关键词,例如CREATE TABLE IF NOT EXISTS table_name

  (2)删表时为避免重复操作,应加上IF EXISTS关键词,例如DROP TABLE IF EXISTS table_name

  (3)添加新列时使用ALTER TABLE table_name ADD COLUMN...,注意比Oracle多了个COLUMN 关键字

  (4)在sqlite中,ALTER语句每次只能添加一列,如果要添加多列,就只能分多次添加

  (5)sqlite支持整型INTEGER、字符串VARCHAR、浮点数FLOAT,但不支持布尔类型。布尔类型数要使用整型保存,如果直接保存布尔数据,在入库时sqlite就会自动将其转为0或1(false,true)

  (6)sqlite 建表时需要一个唯一标识字段,字段名为_ id。 每建一张新表都要例行公事加上该字段定义,具体属性定义为_ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL

  (7)条件语句等号后面的字符串值要用单引号括起来,如果没用单引号括起来则运行时会报错

 

sqliteDatabase是sqlite的数据库管理类,开发者可通过以下代码创建或删除数据库

//创建名叫test.db的数据库(如果不存在就创建它,如果存在就打开它)
sqliteDatabase db=openorCreateDatabase(getFilesDir()+"/test.db",Context.MODE_PRIVATE,null);
//删除名为test.db的数据库
deleteDatabase(getFilesDir()+"/test.db");

为了指导开发者进行sqlite的合理使用,Android提供了一个辅助工具一sqliteOpenHelper, 具体使用步骤如下:

  (1) 新建一个继承自sqliteOpenHelper的数据库操作类,提示重写onCreate和onUpgrade两个方法。其中,onCreate 方法只在第一次打开数据库时执行,在此可进行表结构创建的操作;onUpgrade方法在数据库版本升高时执行,因此可以在onUpgrade函数内部根据新旧版本号进行表结构变更处理。

  (2) 封装保证数据库安全的必要方法,包括获取单例对象、打开数据库连接、关闭数据库连接。

      (获取单例对象:确保App运行时数据库只被打开一次,避免重复打开引起错误。

       打开数据库连接: sqlite有锁机制,即读锁和写锁的处理;故而数据库连接也分两种,读连接可调用sqliteOpenHelper的getReadableDatabase 方法获得,写连接可调用getWritableDatabase获得。

       关闭数据库连接: 数据库操作完毕后,应当调用sqliteDatabase对象的close方法关闭连接。)

  (3) 提供对表记录增删改查的操作方法。


可被sqlite直接使用的数据结构是ContentValues类,类似于映射Map,提供put和get方法用来存取键值对。区别之处在于ContentValues 的键只能是字符串,ContentValues主要用于记录增加和更新操作,即sqliteDatabase的insert 和update方法。

对于查询操作来说,使用的是另一个游标类Cursor。 调用sqliteDatabase 的query 和rawQuery方法时,返回的都是Cursor对象,因此获取查询结果要根据游标的指示一条一条遍历结果集合。Cursor的常用方法可分为3类,说明如下:

(1)游标控制类方法,用于指定游标的状态。

  · close: 关闭游标。

  · isClosed: 判断游标是否关闭。

  · isFirst: 判断游标是否在开头。

  · isLast: 判断游标是否在末尾。

(2)游标移动类方法,把游标移动到指定位置。

  · movetoFirst:移动游标到开头。

  · movetoLast: 移动游标到末尾。

  · movetoNext:移动游标到下一条记录。

  · movetoPrevIoUs:移动游标到上一条记录。

  · move: 往后移动游标若干条记录。

  · movetoPosition: 移动游标到指定位置的记录。

(3)获取记录类方法,可获取记录的数量、类型以及取值。

  · getCount:获取结果记录的数量。

  · getInt:获取指定字段的整型值。(getFloat、getString用法类似)

  · getType:获取指定字段的字段类型

由于数据库操作的特殊性,不方便单独演示某个功能,接下来通过用户注册信息数据库的例子来看一下完整代码:

package USER_CLASS;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.sqliteDatabase;
import android.database.sqlite.sqliteOpenHelper;

import java.util.ArrayList;

/**
 * Created by animator on 2020/1/18.
 */
public class UserDBHelper extends sqliteOpenHelper {
    private static final String DB_NAME="user.db";//数据库名称
    private static final int DB_VERSION=1;//数据库版本号
    private static UserDBHelper mHelper=null;//数据库帮助类的示例
    private sqliteDatabase mDB=null;//数据库的示例
    public final String TABLE_NAME="user_info";//表的名称

    private UserDBHelper(Context context){
        super(context,DB_NAME,null,DB_VERSION);
    }

    private UserDBHelper(Context context,int version){
        super(context,DB_NAME,null,version);
    }

    //利用单例模式获取数据库帮助器的唯一实例
    public static UserDBHelper getInstance(Context context,int version){
        if(version>0&&mHelper==null){
            mHelper=new UserDBHelper(context,version);
        }else if(mHelper==null){
            mHelper=new UserDBHelper(context);
        }
        return mHelper;
    }

    //打开数据库的读连接
    public sqliteDatabase openReadLink(){
        if(mDB==null||!mDB.isopen()){
            mDB=mHelper.getReadableDatabase();
        }
        return mDB;
    }
    //打开数据库的写连接
    public sqliteDatabase openWriteLink(){
        if(mDB==null||!mDB.isopen()){
            mDB=mHelper.getWritableDatabase();
        }
        return mDB;
    }
    //关闭数据库的连接
    public void closeLink(){
        if(mDB!=null&&mDB.isopen()){
            mDB.close();
            mDB=null;
        }
    }

    //创建数据库,执行建表语句
    @Override
    public void onCreate(sqliteDatabase sqliteDatabase) {
        String drop_sql="DROP TABLE IF EIXSTS"+TABLE_NAME+";";
        sqliteDatabase.execsql(drop_sql);
        String create_sql="CREATE TABLE IF NOT EXISTS"+TABLE_NAME+"("+
                "_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"+
                "name VARCHAR NOT NULL,"+"age INTEGER NOT NULL,"+
                "height LONG NOT NULL,"+"weight FLOAT NOT NULL,"+
                "married INTEGER NOT NULL,"+"update_time VARCHAR NOT NULL,"+
                "phone VARCHAR,"+"password VARCHAR"+");";
        sqliteDatabase.execsql(create_sql);
    }


    //修改数据库,执行表结构变更语句
    @Override
    public void onUpgrade(sqliteDatabase sqliteDatabase, int i, int i1) {

    }

    //根据指定条件删除表记录
    public int delete(String condition){
        //执行删除记录动作,该语句返回删除记录的数目
        return mDB.delete(TABLE_NAME,condition,null);
    }

    //往该表中添加多条记录
    public long insert(ArrayList<UserInfo> infoArray){
        long result=-1;
        for(int i=0;i<infoArray.size();i++){
            UserInfo info=infoArray.get(i);
            ArrayList<UserInfo> tempArray=new ArrayList<UserInfo>();
            //如果存在同样的手机号码,则更新记录
            //注意条件语句的等号后面要用单引号括起来
            if(info.phone!=null&&info.phone.length()>0){
                String condition=String.format("phone='%s'",info.phone);
                tempArray=query(condition);
                if(tempArray.size()>0){
                    update(info,condition);
                    result=tempArray.get(0).rowid;
                    continue;
                }
            }
            //不存在唯一性重复的记录,则插入新记录
            ContentValues cv=new ContentValues();
            cv.put("name",info.name);
            cv.put("age",info.age);
            cv.put("height",info.height);
            cv.put("weight",info.weight);
            cv.put("married",info.married);
            cv.put("update_time",info.update_time);
            cv.put("phone",info.phone);
            cv.put("password",info.password);
            //执行插入记录的动作,该语句返回插入记录的行号
            result=mDB.insert(TABLE_NAME,"",cv);
            //添加成功后返回行号,失败后返回-1
            if(result==-1)
                return result;
        }
        return result;
    }

    //根据条件更新指定的表记录
    public int update(UserInfo info,String condition){
        ContentValues cv=new ContentValues();
        cv.put("name",info.name);
        cv.put("age",info.age);
        cv.put("height",info.height);
        cv.put("weight",info.weight);
        cv.put("married",info.married);
        cv.put("update_time",info.update_time);
        cv.put("phone",info.phone);
        cv.put("password",info.password);
        //执行更新记录动作,该语句返回记录更新的数目
        return mDB.update(TABLE_NAME,cv,condition,null);
    }

    //根据指定条件查询记录,并返回结果数据队列
    public ArrayList<UserInfo> query(String condition){
        String sql=String.format("select rowid,_id,name,age,height,weight,married,update_time,phone,password from %s where %s",TABLE_NAME,condition);
        ArrayList<UserInfo> infoArray=new ArrayList<UserInfo>();
        //执行记录查询动作,该语句返回结果集的游标
        Cursor cursor=mDB.rawQuery(sql,null);
        //循环取出游标指向的每条记录
        while(cursor.movetoNext()){
            UserInfo info=new UserInfo();
            info.rowid=cursor.getLong(0);
            info.xuhao=cursor.getInt(1);
            info.name=cursor.getString(2);
            info.age=cursor.getInt(3);
            info.height=cursor.getLong(4);
            info.weight=cursor.getFloat(5);
            //sqlite没有boolean型,用0表示false用1表示true
            info.married=(cursor.getInt(6)==0)?false:true;
            info.update_time=cursor.getString(7);
            info.phone=cursor.getString(8);
            info.password=cursor.getString(9);
            infoArray.add(info);
        }
        cursor.close();
        return infoArray;
    }

    //根据手机号码查询指定记录
    public UserInfo queryByPhone(String phone){
        UserInfo info=null;
        ArrayList<UserInfo> infoArray= query(String.format("phone='%s'",phone));
        if(infoArray.size()>0){
            info=infoArray.get(0);
        }
        return info;
    }
}

Adroid----数据存储之SQLite(1)

Adroid----数据存储之SQLite(1)

简单的介绍一下sqlite。

要点1. sqlite是嵌入式关系型数据库。

要点2. 存储时支持五种数据类型 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)。注意:仍然可以这样创建表结构 CREATE TABLE 表名(_id integer primary key autoincrement,title varvhar(20),content varchar(1000),createtime)。只是当sqlite存储时会自动转换为上边的五大种类型。

要点3. 忽略数据类型检查和数据长度。特殊情况是定义为INTEGER PRIMARY KEY 的字段只能存储64位的整数。

要点4. 支持标准的sql语句。包括增删改查等等。。

使用Android开发数据库应用,是借助于sqliteOpenHelper类完成数据库的创建和升级。sqliteOpenHelper类是一个抽象类,有两个重要方法(onCreate(sqliteDatabase db):初次使用软件时生成数据库表,onUpgrade(sqliteDatabase db,int oldVersion,int newVersion):升级软件时更新数据库表结构)。

如何创建一个数据库?如何创建一个表?下面就给大家一个简单的演示:

<a>定义一个DBHelper类继承sqliteOpenHelper(抽象类)来完成数据库的创建

<b>搭建单元测试环境

<c>进行单元测试:观察数据库是否被创建出来了?数据库的位置:data/data/应用程序的包名/database/xxx.db。

DBHelper类:

public class sqlLiteDB extends sqliteOpenHelper { private static final String db_name = "mydata.db"; private static final int version = 1; public sqlLiteDB(Context context) { super(context,db_name,null,version); } @Override public void onCreate(sqliteDatabase db) { db.execsql("create table data(_id integer primary key,title varchar(50),createtime)"); } @Override public void onUpgrade(sqliteDatabase db,int newVersion) { } }


测试环境的类:

public class sqliteTest extends AndroidTestCase { public void testsqldb(){ sqlLiteDB db = new sqlLiteDB(getContext()); db.getWritableDatabase(); } }

测试运行成功后,去找数据库文件的位置,导出到桌面上,然后打开sqlite,导入这个文件,看一下和自己想像的是否一样。

附上:sqlite数据库,可去我的资源下载。

Android SQLite数据库彻底掌握数据存储

Android SQLite数据库彻底掌握数据存储

sqlite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。

例如:可以在Integer类型的字段中存放字符串,或者在布尔型字段中存放浮点数,或者在字符型字段中存放日期型值。

 但有一种情况例外:定义为INTEGER PRIMARY KEY的字段只能存储64位整数, 当向这种字段保存除整数以外的数据时,将会产生错误。

另外, sqlite 在解析CREATE TABLE 语句时,会忽略 CREATE TABLE 语句中跟在字段名后面的数据类型信息,如下面语句会忽略 name字段的类型信息:

CREATE TABLE person (personid integer primary key autoincrement,name varchar(20)) 

sqlite可以解析大部分标准sql语句,如:

查询语句:select * from 表名 where 条件子句 group by 分组字句 having ... order by 排序子句 (顺序一定不能错)

如:

select * from person 
 
select * from person order by id desc 
 
select name from person group by name having count(*)>1 

分页sql与MysqL类似,下面sql语句获取5条记录,跳过前面3条记录

select * from Account limit 5 offset 3  

或者

select * from Account limit 3,5 

插入语句:

insert into 表名(字段列表) values(值列表)。如:

insert into person(name,age) values(‘小明',3) 

更新语句:

update 表名 set 字段名=值 where 条件子句。如:

update person set name=‘小明‘ where id=10 

删除语句:

delete from 表名 where 条件子句。如:

delete from person  where id=10   

2、使用sqliteOpenHelper对数据库进行版本管理

我们在编写数据库应用软件时,需要考虑这样的问题:因为我们开发的软件可能会安装在很多用户的手机上,如果应用使用到了sqlite数据库,我们必须在用户初次使用软件时创建出应用使用到的数据库表结构及添加一些初始化记录,另外在软件升级的时候,也需要对数据表结构进行更新。那么,我们如何才能实现在用户初次使用或升级软件时自动在用户的手机上创建出应用需要的数据库表呢?总不能让我们在每个需要安装此软件的手机上通过手工方式创建数据库表吧?因为这种需求是每个数据库应用都要面临的,所以在Android系统,为我们提供了一个名为sqliteOpenHelper的抽象类,必须继承它才能使用,它是通过对数据库版本进行管理来实现前面提出的需求。

为了实现对数据库版本进行管理,sqliteOpenHelper类提供了两个重要的方法,分别是onCreate(sqliteDatabase db)和onUpgrade(sqliteDatabase db,int oldVersion,int newVersion),前者用于初次使用软件时生成数据库表,后者用于升级软件时更新数据库表结构。当调用sqliteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的sqliteDatabase实例的时候,如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用,在onCreate()方法里可以生成数据库表结构及添加一些应用使用到的初始化数据。onUpgrade()方法在数据库的版本发生变化时会被调用,一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2(有同学问设置为3行不行?当然可以,如果你愿意,设置为100也行),并且在onUpgrade()方法里面实现表结构的更新。当软件的版本升级次数比较多,这时在onUpgrade()方法里面可以根据原版号和目标版本号进行判断,然后作出相应的表结构及数据更新。

getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的sqliteDatabase实例。但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase()打开数据库就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。

public class DatabaseHelper extends sqliteOpenHelper { 
 
    //类没有实例化,是不能用作父类构造器的参数,必须声明为静态 
 
     private static final String name = "count"; //数据库名称 
 
     private static final int version = 1; //数据库版本 
 
     public DatabaseHelper(Context context) { 
 
       //第三个参数CursorFactory指定在执行查询时获得一个游标实例的工厂类,设置为null,代表使用系统默认的工厂类 
 
        super(context,name,null,version); 
 
     } 
 
    @Override 
    public void onCreate(sqliteDatabase db) { 
 
       db.execsql("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement,name varchar(20),age INTEGER)");   
 
     } 
 
    @Override  
    public void onUpgrade(sqliteDatabase db,int newVersion) { 
 
        db.execsql("ALTER TABLE person ADD phone VARCHAR(12)"); //往表中增加一列 
 
     } 
} 

在实际项目开发中,当数据库表结构发生更新时,应该避免用户存放于数据库中的数据丢失。

3、使用sqliteDatabase操作sqlite数据库

Android提供了一个名为sqliteDatabase的类,该类封装了一些操作数据库的API,使用该类可以完成对数据进行添加(Create)、查询(Retrieve)、更新(Update)和删除(Delete)操作(这些操作简称为CRUD)。对sqliteDatabase的学习,我们应该重点掌握execsql()和rawQuery()方法。 execsql()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的sql语句; rawQuery()方法用于执行select语句。

execsql()方法的使用例子:

sqliteDatabase db = ....; 
 
db.execsql("insert into person(name,age) values('炸死特',4)"); 
 
db.close(); 

执行上面sql语句会往person表中添加进一条记录,在实际应用中, 语句中的“炸死特”这些参数值会由用户输入界面提供,如果把用户输入的内容原样组拼到上面的insert语句, 当用户输入的内容含有单引号时,组拼出来的sql语句就会存在语法错误。要解决这个问题需要对单引号进行转义,也就是把单引号转换成两个单引号。有些时候用户往往还会输入像“ & ”这些特殊sql符号,为保证组拼好的sql语句语法正确,必须对sql语句中的这些特殊sql符号都进行转义,显然,对每条sql语句都做这样的处理工作是比较烦琐的。 sqliteDatabase类提供了一个重载后的execsql(String sql,Object[] bindArgs)方法,使用这个方法可以解决前面提到的问题,因为这个方法支持使用占位符参数(?)。

例子如下:

sqliteDatabase db = ....; 
 
db.execsql("insert into person(name,age) values(?,?)",new Object[]{"炸死特",4});  
 
db.close(); 

execsql(String sql,Object[] bindArgs)方法的第一个参数为sql语句,第二个参数为sql语句中占位符参数的值,参数值在数组中的顺序要和占位符的位置对应。

sqliteDatabase的rawQuery() 用于执行select语句,使用例子如下:

sqliteDatabase db = ....; 
 
Cursor cursor = db.rawQuery(“select * from person”,null); 
 
while (cursor.movetoNext()) { 
 
 int personid = cursor.getInt(0); //获取第一列的值,第一列的索引从0开始 
 
 String name = cursor.getString(1);//获取第二列的值 
 
 int age = cursor.getInt(2);//获取第三列的值 
 
} 
 
cursor.close(); 
 
db.close(); 

rawQuery()方法的第一个参数为select语句;第二个参数为select语句中占位符参数的值,如果select语句没有使用占位符,该参数可以设置为null。带占位符参数的select语句使用例子如下:

Cursor cursor = db.rawQuery("select * from person where name like ? and age=?",new String[]{"%炸死特%","4"}); 

Cursor是结果集游标,用于对结果集进行随机访问,如果大家熟悉jdbc, 其实Cursor与JDBC中的ResultSet作用很相似。使用movetoNext()方法可以将游标从当前行移动到下一行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。另外Cursor 还有常用的movetoPrevIoUs()方法(用于将游标从当前行移动到上一行,如果已经移过了结果集的第一行,返回值为false,否则为true )、movetoFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true )和movetoLast()方法(用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true ) 。

除了前面给大家介绍的execsql()和rawQuery()方法, sqliteDatabase还专门提供了对应于添加、删除、更新、查询的操作方法: insert()、delete()、update()和query() 。这些方法实际上是给那些不太了解sql语法的菜鸟使用的,对于熟悉sql语法的程序员而言,直接使用execsql()和rawQuery()方法执行sql语句就能完成数据的添加、删除、更新、查询操作。

Insert()方法用于添加数据,各个字段的数据使用ContentValues进行存放。 ContentValues类似于MAP,相对于MAP,它提供了存取数据对应的put(String key,Xxx value)和getAsXxx(String key)方法,  key为字段名称,value为字段值,Xxx指的是各种常用的数据类型,如:String、Integer等。

sqliteDatabase db = databaseHelper.getWritableDatabase(); 
 
ContentValues values = new ContentValues(); 
 
values.put("name","炸死特"); 
 
values.put("age",4); 
 
long rowid = db.insert(“person”,values);//返回新添记录的行号,与主键id无关 

不管第三个参数是否包含数据,执行Insert()方法必然会添加一条记录,如果第三个参数为空,会添加一条除主键之外其他字段值为Null的记录。Insert()方法内部实际上通过构造insert sql语句完成数据的添加,Insert()方法的第二个参数用于指定空值字段的名称,相信大家对该参数会感到疑惑,该参数的作用是什么?

是这样的:如果第三个参数values 为Null或者元素个数为0, 由于Insert()方法要求必须添加一条除了主键之外其它字段为Null值的记录,为了满足sql语法的需要, insert语句必须给定一个字段名,如:insert into person(name) values(NULL),倘若不给定字段名 , insert语句就成了这样: insert into person() values(),显然这不满足标准sql的语法。对于字段名,建议使用主键之外的字段,如果使用了INTEGER类型的主键字段,执行类似insert into person(personid) values(NULL)的insert语句后,该主键字段值也不会为NULL。如果第三个参数values 不为Null并且元素的个数大于0 ,可以把第二个参数设置为null。

关于此处insert的更加详细讲解在这里http://blog.csdn.net/jason0539/article/details/9977175

delete()方法的使用:

sqliteDatabase db = databaseHelper.getWritableDatabase(); 
 
db.delete("person","personid<?",new String[]{"2"}); 
 
db.close(); 

上面代码用于从person表中删除personid小于2的记录。

update()方法的使用:

sqliteDatabase db = databaseHelper.getWritableDatabase(); 
 
ContentValues values = new ContentValues(); 
 
values.put(“name”,“炸死特”);//key为字段名,value为值 
 
db.update("person",values,"personid=?",new String[]{"1"});  
 
db.close(); 

上面代码用于把person表中personid等于1的记录的name字段的值改为“炸死特”。

query()方法

实际上是把select语句拆分成了若干个组成部分,然后作为方法的输入参数:

sqliteDatabase db = databaseHelper.getWritableDatabase(); 
 
Cursor cursor = db.query("person",new String[]{"personid,age"},"name like ?",new String[]{"%炸死特%"},"personid desc","1,2"); 
 
while (cursor.movetoNext()) { 
 
     int personid = cursor.getInt(0); //获取第一列的值,第一列的索引从0开始 
 
     String name = cursor.getString(1);//获取第二列的值 
 
     int age = cursor.getInt(2);//获取第三列的值 
 
} 
 
cursor.close(); 
 
db.close(); 

上面代码用于从person表中查找name字段含有“炸死特”的记录,匹配的记录按personid降序排序,对排序后的结果略过第一条记录,只获取2条记录。

query(table,columns,selection,selectionArgs,groupBy,having,orderBy,limit)方法各参数的含义:

table:表名。相当于select语句from关键字后面的部分。如果是多表联合查询,可以用逗号将两个表名分开。

columns:要查询出来的列名。相当于select语句select关键字后面的部分。

selection:查询条件子句,相当于select语句where关键字后面的部分,在条件子句允许使用占位符“?”

selectionArgs:对应于selection语句中占位符的值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常。

groupBy:相当于select语句group by关键字后面的部分

having:相当于select语句having关键字后面的部分

orderBy:相当于select语句order by关键字后面的部分,如:personid desc,age asc;

limit:指定偏移量和获取的记录数,相当于select语句limit关键字后面的部分。

数据库实例:

这是我在练习中的一个数据库帮助类,直接复制过来,可以作为了解数据库的模板

package jason.demo; 
 
import android.content.Context; 
import android.content.ContentValues; 
import android.database.Cursor; 
import android.database.sqlException; 
import android.database.sqlite.sqliteOpenHelper; 
import android.database.sqlite.sqliteDatabase; 
import android.database.sqlite.sqliteQueryBuilder; 
 
class RestaurantHelper extends sqliteOpenHelper { 
  private static final String DATABASE_NAME="lunchlist.db";//数据库名称 
  private static final int SCHEMA_VERSION=2;//版本号,则是升级之后的,升级方法请看onUpgrade方法里面的判断 
   
  public RestaurantHelper(Context context) {//构造函数,接收上下文作为参数,直接调用的父类的构造函数 
    super(context,DATABASE_NAME,SCHEMA_VERSION); 
  } 
   
  @Override 
  public void onCreate(sqliteDatabase db) {//创建的是一个午餐订餐的列表,id,菜名,地址等等 
    db.execsql("CREATE TABLE restaurants (_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,address TEXT,type TEXT,notes TEXT,phone TEXT);"); 
  } 
 
  @Override 
  public void onUpgrade(sqliteDatabase db,int newVersion) { 
    if (oldVersion==1 && newVersion==2) {//升级判断,如果再升级就要再加两个判断,从1到3,从2到3 
      db.execsql("ALTER TABLE restaurants ADD phone TEXT;"); 
    } 
  } 
 
  public Cursor getAll(String where,String orderBy) {//返回表中的数据,where是调用时候传进来的搜索内容,orderby是设置中传进来的列表排序类型 
    StringBuilder buf=new StringBuilder("SELECT _id,address,type,notes,phone FROM restaurants"); 
     
    if (where!=null) { 
      buf.append(" WHERE "); 
      buf.append(where); 
    } 
     
    if (orderBy!=null) { 
      buf.append(" ORDER BY "); 
      buf.append(orderBy); 
    } 
     
    return(getReadableDatabase().rawQuery(buf.toString(),null)); 
  } 
   
  public Cursor getById(String id) {//根据点击事件获取id,查询数据库 
    String[] args={id}; 
 
    return(getReadableDatabase() 
            .rawQuery("SELECT _id,phone FROM restaurants WHERE _ID=?",args)); 
  } 
   
  public void insert(String name,String address,String type,String notes,String phone) { 
    ContentValues cv=new ContentValues(); 
           
    cv.put("name",name); 
    cv.put("address",address); 
    cv.put("type",type); 
    cv.put("notes",notes); 
    cv.put("phone",phone); 
     
    getWritableDatabase().insert("restaurants","name",cv); 
  } 
   
  public void update(String id,String name,String phone) { 
    ContentValues cv=new ContentValues(); 
    String[] args={id}; 
     
    cv.put("name",phone); 
     
    getWritableDatabase().update("restaurants",cv,"_ID=?",args); 
  } 
   
  public String getName(Cursor c) { 
    return(c.getString(1)); 
  } 
   
  public String getAddress(Cursor c) { 
    return(c.getString(2)); 
  } 
   
  public String getType(Cursor c) { 
    return(c.getString(3)); 
  } 
   
  public String getNotes(Cursor c) { 
    return(c.getString(4)); 
  } 
   
  public String getPhone(Cursor c) { 
    return(c.getString(5)); 
  } 
} 
 

那么这个帮助类该如何使用呢,下面举个列子,也是从代码里摘出来的一段

public class LunchList extends ListActivity { 
 Cursor model=null;//用来存储查询的数据 
 RestaurantAdapter adapter=null;//上面自定义的数据库帮助类 
 public void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.main); 
 
  helper=new RestaurantHelper(this);//参数是上下文 
 
  initList();//初始化listview列表,省略了很多,大体能明白使用数据库流程就行啦 
 
} 
 
private void initList() { 
 if (model!=null) { 
  stopManagingCursor(model); 
  model.close(); 
 } 
  
 String where=null; 
 
 if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {//如果有查询指令则根据查询内容从数据库获取表中所有满足条件数据 
  where="name LIKE \"%"+getIntent().getStringExtra(SearchManager.QUERY)+"%\""; 
 } 
 model=helper.getAll(where,prefs.getString("sort_order","name"));//调用帮助类中的方法获取数据 
 startManagingCursor(model); 
 adapter=new RestaurantAdapter(model);//设置adapter 
 setlistadapter(adapter);//在列表中显示出来 
 } 

这里只举例了查询,增删改操作都类似,只是用helper调用一下需要的方法就行了,参数传对就没有问题.

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

android studio数据存储建立SQLite数据库实现增删查改

android studio数据存储建立SQLite数据库实现增删查改

实验目的:

分别使用sqlite3工具和Android代码的方式建立SQLite数据库。在完成建立数据库的工作后,编程实现基本的数据库操作功能,包括数据的添加、删除和更新。

实验要求:

  • 1.创建一个学生管理的应用,基本信息包含学生姓名,班级,学号。采用数据库存储这些信息。
  • 2.应用应该至少包含信息录入和删除功能。
  • 3.数据显示考虑采用ListView。

实验效果:

工程结构:

源代码:

DBAdapter.java

package com.example.shiyan6_sqlite;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;

public class DBAdapter {

 private static final String DB_NAME = "student.db";
 private static final String DB_TABLE = "peopleinfo";
 private static final int DB_VERSION = 1;

 public static final String KEY_ID = "_id";
 public static final String KEY_NAME = "name";
 public static final String KEY_BANJI = "banji";
 public static final String KEY_XUEHAO = "xuehao";

 private SQLiteDatabase db;
 private final Context context;
 private DBOpenHelper dbOpenHelper;

 public DBAdapter(Context _context) {
  context = _context;
 }

 public void close() {
  if(db !=null)
  {
   db.close();
   db=null;
  }
 }

 public void open() throws SQLiteException {
  dbOpenHelper = new DBOpenHelper(context, DB_NAME, null, DB_VERSION);
  try {
   db = dbOpenHelper.getWritableDatabase();
  }
  catch (SQLiteException ex) {
   db = dbOpenHelper.getReadableDatabase();
  }
 }


 public long insert(People people) {
  ContentValues newValues = new ContentValues();
  newValues.put(KEY_NAME, people.Name);
  newValues.put(KEY_BANJI, people.Banji);
  newValues.put(KEY_XUEHAO, people.Xuehao);

  return db.insert(DB_TABLE, null, newValues);
 }


 public People[] queryAllData() {
  Cursor results =  db.query(DB_TABLE, new String[] { KEY_ID, KEY_NAME, KEY_BANJI, KEY_XUEHAO},
    null, null, null, null, null);
  return ConvertToPeople(results);
 }

 public People[] queryOneData(long id) {
  Cursor results =  db.query(DB_TABLE, new String[] { KEY_ID, KEY_NAME, KEY_BANJI, KEY_XUEHAO},
    KEY_ID + "=" + id, null, null, null, null);
  return ConvertToPeople(results);
 }

 @SuppressLint("Range")
 private People[] ConvertToPeople(Cursor cursor){
  int resultCounts = cursor.getCount();
  if (resultCounts == 0 || !cursor.moveToFirst()){
   return null;
  }
  People[] peoples = new People[resultCounts];
  for (int i = 0 ; i<resultCounts; i++){
   peoples[i] = new People();
   peoples[i].ID = cursor.getInt(0);
   peoples[i].Name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
   peoples[i].Banji = cursor.getString(cursor.getColumnIndex(KEY_BANJI));
   peoples[i].Xuehao = cursor.getString(cursor.getColumnIndex(KEY_XUEHAO));
   cursor.moveToNext();
  }
  return peoples;
 }

 public long deleteAllData() {
  return db.delete(DB_TABLE, null, null);
 }

 public long deleteOneData(long id) {
  return db.delete(DB_TABLE,  KEY_ID + "=" + id, null);
 }

 public long updateOneData(long id , People people){
  ContentValues updateValues = new ContentValues();
  updateValues.put(KEY_NAME, people.Name);
  updateValues.put(KEY_BANJI, people.Banji);
  updateValues.put(KEY_XUEHAO, people.Xuehao);

  return db.update(DB_TABLE, updateValues,  KEY_ID + "=" + id, null);
 }

 private static class DBOpenHelper extends SQLiteOpenHelper {

  public DBOpenHelper(Context context, String name, CursorFactory factory, int version) {
   super(context, name, factory, version);
  }

  private static final String DB_CREATE = "create table " +
    DB_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " +
    KEY_NAME+ " text not null, " + KEY_BANJI+ " text not null," + KEY_XUEHAO + " text not null);";

  @Override
  public void onCreate(SQLiteDatabase _db) {
   _db.execSQL(DB_CREATE);
  }

  @Override
  public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {
   _db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
   onCreate(_db);
  }
 }
}

People.java

package com.example.shiyan6_sqlite;

public class People {
 public int ID = -1;
 public String Name;
 public String Banji;
 public String Xuehao;

 @Override
 public String toString(){
  String result = "";
  result += "ID:" + this.ID + ",";
  result += "姓名:" + this.Name + ",";
  result += "班级:" + this.Banji + ", ";
  result += "学号:" + this.Xuehao;
  return result;
 }
}


MainActivity.java

package com.example.shiyan6_sqlite;

import androidx.appcompat.app.AppCompatActivity;

import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    EditText e_xm,e_nl,e_sg,e_id;
    TextView t_1;
    Button b_add,b_allsee,b_clearsee,b_alldel,b_delid,b_seeid,b_updid;
    DBAdapter dbAdapter;
    SQLiteDatabase db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        e_xm=findViewById(R.id.e_xm);
        e_nl=findViewById(R.id.e_nl);
        e_sg=findViewById(R.id.e_sg);
        b_add=findViewById(R.id.b_add);
        b_allsee=findViewById(R.id.b_allsee);
        b_clearsee=findViewById(R.id.b_clearall);
        b_alldel=findViewById(R.id.b_delall);
        b_delid=findViewById(R.id.b_delid);
        b_seeid=findViewById(R.id.b_seeid);
        b_updid=findViewById(R.id.b_updid);
        e_id=findViewById(R.id.e_id);
        t_1=findViewById(R.id.t_1);
        dbAdapter=new DBAdapter(this);
        dbAdapter.open();


        b_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                People t=new People();
                t.Name=e_xm.getText().toString();
                t.Banji=e_nl.getText().toString();
                t.Xuehao=e_sg.getText().toString();
                long colunm=dbAdapter.insert(t);
                if (colunm == -1 ){
                    t_1.setText("添加过程错误!");
                } else {
                    t_1.setText("成功添加数据,ID:"+String.valueOf(colunm));
                }
            }
        });

        b_allsee.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                People [] peoples =dbAdapter.queryAllData();
                if (peoples == null){
                    t_1.setText("数据库中没有数据");
                    return;
                }
                String t="数据库:\n";
                for(int i=0;i<peoples.length;++i){
                    t+=peoples[i].toString()+"\n";
                }
                t_1.setText(t);
            }
        });

        b_clearsee.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                t_1.setText("");
            }
        });

        b_alldel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dbAdapter.deleteAllData();
                t_1.setText("已删除所有数据!");
            }
        });

        b_delid.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int id=Integer.parseInt(e_id.getText().toString());
                long result=dbAdapter.deleteOneData(id);
                String msg = "删除ID为"+e_id.getText().toString()+"的数据" + (result>0?"成功":"失败");
                t_1.setText(msg);
            }
        });

        b_seeid.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int id=Integer.parseInt(e_id.getText().toString());
                People people[]=dbAdapter.queryOneData(id);
                if(people==null){
                    t_1.setText("Id为"+id+"的记录不存在!");
                }
                else{
                    t_1.setText("查询成功:\n"+people[0].toString());
                }
            }
        });

        b_updid.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int id=Integer.parseInt(e_id.getText().toString());
                People t=new People();
                t.Name=e_xm.getText().toString();
                t.Banji=e_nl.getText().toString();
                t.Xuehao=e_sg.getText().toString();
                long n=dbAdapter.updateOneData(id,t);
                if (n<0){
                    t_1.setText("更新过程错误!");
                } else {
                    t_1.setText("成功更新数据,"+String.valueOf(n)+"条");
                }
            }
        });
    }

    @Override
    protected void onStop() {
        super.onStop();
        dbAdapter.close();
    }
}

到此这篇关于vandroid studio数据存储建立SQLite数据库实现增删查改的文章就介绍到这了,更多相关数据存储建立SQLite数据库实现增删查改内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

您可能感兴趣的文章:
  • Android 通过SQLite数据库实现数据存储管理
  • Android四种数据存储的应用方式
  • Android基础教程数据存储之文件存储
  • Android SharedPreferences实现数据存储功能
  • 详解Android数据存储—使用SQLite数据库
  • Android数据存储方式操作模式解析

Android – 将敏感数据存储在sqlite数据库中

Android – 将敏感数据存储在sqlite数据库中

我需要在 Android应用程序的sqlite数据库中存储敏感数据.

我如何确保这些数据是非常安全的?
我知道我可以使用密钥加密数据,但是我在哪里存储该密钥?我不想要求用户填写一个密钥,我只是想让它自己工作.
因为我怕逆向工程,我也不想在代码中加一个加密密钥.

我发现大约有SQLCipher.它说这是一种非常安全的方式来加密数据库中的数据,但为什么会这样呢?我还需要保留一个钥匙来解锁这些信息吗?或者这真的是确保数据安全的完美方式吗?

如果不是,在sqlite数据库中存储敏感数据的(几乎)失败的方法是什么?

解决方法

对称加密需要一个密钥加密和相同的密钥进行解密.没有办法.

不要将密钥存储在代码中,因为它可以被反编译(就像你所说的).

请求用户首次使用密码,并使用PBKDF2导出加密中使用的密码安全密钥.

用户必须输入密码,或者您需要将其存储在内存中.我要做的是,请用户指定密钥缓存在内存中用于解密的持续时间.

如果持续时间过期,用户将不得不再次输入密码.

我没有彻底检查sqlCipher,但它说它使用AES-256. AES是一种对称加密算法,它需要一个密钥加密和相同的密钥来解密.

我们今天的关于Android数据存储之SQLite数据库的分享就到这里,谢谢您的阅读,如果想了解更多关于Adroid----数据存储之SQLite(1)、Android SQLite数据库彻底掌握数据存储、android studio数据存储建立SQLite数据库实现增删查改、Android – 将敏感数据存储在sqlite数据库中的相关信息,可以在本站进行搜索。

本文标签: