数据存储技术

安卓提供了三种方式用于简单的数据持久化功能:文件储存,SharedPreference存储,数据库储存。

文件储存

用于保存一些简单的文本数据或二进制数据。
使用到的方法:Context类中提供了openFileOutput(String str,int a)方法 和 openFileInput(String str)方法

openFileOutput()方法:

文件默认的存储到data/data// files/目录下。
拥有两个参数 第一个是文件名 第二个是文件的操作方式字段。

文件的操作方式:
MODE_PRIVATE当指定同样文件名时会覆盖原文件中的内容
MODE_APPEND当该文件已存在时就往文件中追加内容,不会创建新文件

文件存储使用:java流

FileOutputStream out = openFileOutput("save", MODE_PRIVATE);
//方法得到的是一个FileOutputStream对象
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
//用OutputStreamWriter输出流读写器包装输出流,再用缓冲流包装输出流。
writer.write(text);//调用读写器方法写入数据text
openFileIntput()方法:
FileInputStream in = openFileInput("save");
//方法得到的是一个FileInputStream对象
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
//用InputStreamReader输入流读写器包装输出流,再用缓冲流包装输入流。
String len = "";
StringBuilder content=new StringBuilder();
while ((len = reader.readLine()) != null) {//调用读写器方法按行读取数据
content.append(len) };//每行均黏贴入缓冲域
content.toString();//缓冲域的内容转化为String

——————————————————————————————————————————

SharedPreferences储存:

sharedPreferences是采用键值对的方式存储数据的,它的储存方式比文件储存简单易用。

getSharedPreferences()方法:

默认的储存路径是:data/data//shared_prefs/下
此方法接受两个参数:

第一个参数是文件名,如果文件不存在则会创建一个。
第二个参数是指定操作模式:
MODE_PRIVATE 表示只有当前应用程序可以对sharedPreferences文件读写。
MODE_MULTI_PROCESS 用于会有多个进程中对同一个sharedPreferences文件读取,6.0中废弃。

存入
SharedPreferences.Editor  editor = getSharedPreferences("save", MODE_PRIVATE).edit();
//拿到编辑器对象才能放入数据
editor.putString("name","Tom");
editor.apply();//提交放入的数据
取出
SharedPreferences pref= getSharedPreferences("save", MODE_PRIVATE);
String str =pref.getString(''name","");//第二个参数为拿不到所设置的默认值

——————————————————————————————————————————

数据库储存-SQLiteOpenHelper:

当我们需要储存大量复杂的关系型数据的时候,前两种方法就有点力不从心了,例如保存短息,联系人信息等,这个时候我们就可以使用安卓内置的数据库。
安卓系统内置了SQLLite数据库,它支持SQL语法,还遵循数据库的ACID事务,是一款轻量级的数据库。

创建数据库

1.创建数据库需要继承SQLiteOpenHelper,我们需要重写它的两个方法,onCreate()和onUpgrade().分别在这连个方法中创建和升级数据库。

2.SQLiteOpenHelper的构造方法,四个参数 第一个Context 第二个 数据库名 第三个 查询数据时返回一个自定义的Cursor,一般都传null , 第四个是数据库的版本号。

3.SQLiteOpenHelper中有两个非常重要的实例方法,getReadableDatabase()和getWritableDatabase()。这两个方法都可以创建和打开一个现有的数据库。当磁盘空间满的时候getReadableDatabase()会打开一个只读的数据库,getWritableDatabase()会出现异常。磁盘空间未满的时候都是创建或打开一个可读可写的数据库,并返回一个SQLiteDatabase对象,可以用其进行CRUD操作。

4.在SQLite数据库中数据类型 integer表示整形 real表示浮点型 text 表示文本类型 blob表示二进制类型,数据库文件会存放在data/data//databases/下。


//MySQLiteOpenHelper实现类
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
     
    public static final String Create_contact = "create table person(_id integer primary key autoincrement, " +
            "name char(10), " +
            "salary char(20), " +
            "phone integer(20))";
 
    public MySQLiteOpenHelper(Context context, String name,CursorFactory factory, int version) {
        super(context, name, factory, version);
        mcontext = context;
    }
 
    public void onCreate(SQLiteDatabase db) {
        //当创建数据库的时候会调用此方法在此方法中创建表
        db.execSQL(Create_contact);
        Toast.makeText(mcontext, "数据库创建了", 0).show();
    }
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}
在数据库实现类中使用建表语言:

由于实现类继承了SQLiteOpenHelper,由此获得了SQLiteDatabase的操作对象与功能,并传入onCreate();与onUpgrade();在这两个方法中,就可以使用SQLiteDatabase的execSQL(String str)语句
执行字符串str中的建表语句。

升级数据库:

重写实现类 onUpgrade()方法。
并且修改实现类构造函数中的参数使其大于上一版本。

 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {//系统自动完成上一次new实现类对象的版本号传递
        case 1:
            db.execSQL(Create_sms);// 如果用户从1版本升级过来的话,就不会创建两张表而是再升级中添加一张表
         case 2:
            db.execSQL("alter table person add column category_id integer");// 如果用户从2版本升级过来的话,就会直接添加一个列字段
        default:
        }
Create/insert & Update/update & Delete/delete:增删改
//创建帮助类实例
MySQLiteOpenHelper  dbHelper=new MySQLiteOpenHelper(this,"SQL.db",null,0);
//获得操作数据库的功能对象
SQLiteDatabase db= dbHelper.getWritableDatabase();
//利用赋值容具类ContentValues完成对一行多列数据的转存
ContentValues values=new ContentValues();

//增:
values.put("column1","text1")
values.put("column2","text2")
...
//第二个参数nullColumnHack:当values参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许插入一个空行)
//为了防止这种情况,在这里指定一个列名,到时候如果发现将要插入的行为空行时,就会将你指定的这个列名的值设为null,然后再向数据库中插入。
db.insert(String table(插入表名),columns, values);

//删: 删除指定列满足条件的数据   
//第二个参数(selection:查询条件)相当于SQL语句中where,?是一个占位符,由后一个参数str提供
db.delete(String table(删除表名),"column+关系式+?",string str);

//改:更改指定列满足条件的数据
//第三个参数(selection:查询条件)相当于SQL语句中where,?是一个占位符,由后一个参数str提供
//由values提供列名与修改内容
db.update(String table(更新表名),values,"column+关系式+?",string str);
Retrieve/select:查询

query(String table,String []Columns, String selection, String[]selectionArgs, String having, string orderBy);共7个参数 :
table:表名,不能为null
columns:要查询的列名,可以是多个,可以为null,表示查询所有列
selection:查询条件,比如id=? and name=? 可以为null
selectionArgs:对查询条件赋值,一个问号(占位符)对应一个值,按顺序 可以为null
groupBy: 指定需要按第二个参数来groupby分组的列,可以为null
having:语法having设置分组条件,可以为null
orderBy:指定查询结果排序方法,可以为null

调用query都会返回一个Cursor对象,对这个对象进行遍历即可得到查询后的所有数据

Cursor cursor = db.query("person", null, null, null, null, null, null);
  if(cursor.moveToFirst()) {
do{
 String colunm1 = cursor.getString(cursor.getColumnIndex("colunm1"));
 String colunm2 = cursor.getString(cursor.getColumnIndex("colunm2"));
.....
 }while(cursor.moveToNext());
}
cursor.close();
此外,也可使用db.execSQL(String str)执行SQL语言完成增删改,查询则使用db.rawQuery(String str);

——————————————————————————————————————————

数据库储存-LitePal:

快速配置
  1. 引入Jar包或源码
    LitePal的开源已经提交到 jcenter,故我们想要使用,只需要编辑app/build.gradle文件,在dependencies闭包中添加以下内容:
    compile 'org.litepal.android:core:1.4.1' //1.4.1是版本号,最新版本号在引用可见

  2. 配置litepal.xml
    接着在项目的main目录下创建assets目录并新建一个litepal.xml文件,并将以下代码拷贝进去:

  
  
      
      
      
      

配置文件相当简单,用于设定数据库的名字,用于设定数据库的版本号,用于设定所有的映射模型,我们稍后就会用到。

  1. 配置LitePalApplication
    由于操作数据库时需要用到Context,而我们显然不希望在每个接口中都去传一遍这个参数,那样操作数据库就显得太繁琐了。因此,LitePal使用了一个方法来简化掉Context这个参数,只需要在AndroidManifest.xml中配置一下LitePalApplication,所有的数据库操作就都不用再传Context了,如下所示:
  
      
    ...  
      
 
创建数据库

配置映射:

    package com.example.databasetest.model;  
   
    public class News {  
    //定义字段,可以进行对象关系映射的数据类型一共有8种,int、short、long、float、double、boolean、String和   Date。
    //只要是声明成这8种数据类型的字段都会被自动映射到数据库表中,并不需要进行任何额外的配置。
    //自动生成get,set方法
    }  

完成映射:

  
  
      
  
      
  
      
        //添加到关系类列表  
      
 

成功创建:
在活动中运行:LitePal.getDatabase();方法则成功完成创建。

升级数据库

不需要去编写任何与升级相关的逻辑,也不需要关心程序是从哪个版本升级过来的,唯一要做的就是确定好最新的Model结构是什么样的,然后将litepal.xml中的版本号加1,所有的升级逻辑就都会自动完成了。LitePal确实将数据库表的升级操作变得极度简单,使很多程序员可以从维护数据库表升级的困扰中解脱出来。

Create/insert & Update/update & Delete/delete:增删改

进行CRUD操作时就不行了,LitePal要求所有的实体类都要继承自DataSupport这个类
【具体操作参见:】http://blog.csdn.net/guolin_blog/article/details/39345833

添加:每new出一个对应类的对象,则为添加一行数据,save();方法提交,save()返回为存储的结果。调用save();后则这个对象为已存储,此时再调用isSave():则为TRUE

修改:
1.先调用set方法设置新属性,然后使用 该对象.update(long id) //快捷修改,会默认传入类对象并省略values
2.如果是需要设置条件的复杂修改,则需要与ContentValues values联用,使用DataSupport.update();或DataSupport.updateAll();

删除:与修改类似,不过是deleteAll();与delete();方法。

Retrieve/select:查询

简单查询:

News news = DataSupport.find(News.class, 1); //查id为1的记录
News firstNews = DataSupport.findFirst(News.class); //查第一条
News lastNews = DataSupport.findLast(News.class);
List newsList = DataSupport.findAll(News.class, 1, 3, 5, 7);  //后边传入任意id,无则为全部

连缀查询:原本query的多个参数被封装成各自的方法,在DataSupport.find(.class)前连缀使用

激进查询:

News news = DataSupport.find(News.class, 1, true);  //这会将和news表关联的所有表中的数据也一起查出来

该查询效率不高,最佳写法是在Model类中添加了一个get()方法,而这个方法的内部就是使用了一句连缀查询,查出了当前类对象关联的所有类对象。

此外,也可使用原生语句SQL执行SQL语言完成查询;
    Cursor cursor = DataSupport.findBySQL("select * from news where commentcount>?", "0");  

——————————————————————————————————————————
【github新版本】https://github.com/LitePalFramework/LitePal
【配置问题】http://blog.csdn.net/guolin_blog/article/details/38556989
【LitePal实现表内连接】 http://blog.csdn.net/guolin_blog/article/details/39207945
【LitePal实现查询】 http://blog.csdn.net/guolin_blog/article/details/40153833

——————————————————————————————————————————
【样本方法实例:】http://blog.csdn.net/itluochen/article/details/52605392
【数据库CRUD操作参数详解】http://blog.csdn.net/nomisshe/article/details/17797631

你可能感兴趣的:(数据存储技术)