第六章--绕不开的数据库SQLite

两周就和群里的人有了好大的差距,在绵阳的日子真不好熬,也想把它当作一种磨练,但一边每天去实习,心里总是挂着学习这个的事,心里焦灼,也想向辅导员请假回学校,但是好像在老师眼中,考研学习才是重要的事,其他学习就不重要。喝个鸡汤,加油你可以的。。。。

SQLite数据库

还记得大二时学的数据库,当初还想好好听课,坐在第一排,然而后面就开始在课堂上睡觉。期末考试的时候,复习了几天,记住了一些语句,然后就去参加考试。全学院要学的大课,安排了好多考场,不过是选修,后面去考的人寥寥无几。这样学知识的后果就是学完就忘,并且理解的太浅,或者说没有理解,和学过的数据结构一样。

以上都是些废话。

在android中使用数据库比在java中要简单,最起码过程简单。先来介绍一下SQLite,她是一个嵌入式的数据库引擎,专门适用于资源有限的设备上适量数据的存取。

它有以下的优点:

  • 轻量级:使用SQLite数据库不需要向mysql一样安装,启动服务进程,它自己只是一个文件
  • 独立:SQLite的核心引擎本身不依赖第三方的软件,有点类似那种绿色软件,不需要软件
  • 隔离:我理解的就是它只是一个文件,不依赖其他存在,所以隔离性好
  • 跨平台:除了主流操作系统 windows,linux之后,SQLite还支持其它一些不常用的操作系统。
  • 多语言接口:SQLite 数据库支持多语言编程接口。
  • 安全:SQLite 数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只能有一个可以写入数据。

SQLiteDatabase

android提供了SQLiteDatabase代表一个数据库,一旦获得了这个对象就可以用来操作数据库了。首先SQLite有静态方法openDatabase(..)和openOrCreateDatabase(..)方法来打开和创建数据库,android提供了一种更加优雅的方式来创建和更新数据库,SQLiteOpenHelper这个类,所以以下就是从介绍它开始

SQLiteOpenHelper类

创建一个类继承SQLiteOpenHelper

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 *
 * Created by W on 2016/8/13.
 */
public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String USER_TABLE_NAME = "user";
    public static final String USERNAME = "username";
    public static final String AGE = "age";
    public static final String DATABASE_NAME = "text.db";
    public static final int VERSION = 1;

    public DatabaseHelper(Context context ) {
        //name:数据库的名字,factory:null,版本
        super(context, DATABASE_NAME, null,  VERSION);
    }

    //创建数据库
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table " + USER_TABLE_NAME + " (" + USERNAME + " varchar(20) not null, " + AGE + " varchar(60) not null);");
    }

    //升级数据库
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //TODO:an database upgrade

    }
}

该类的构造器中传入上下文,数据库的名字后缀是.db,null,版本号。下面两个必须重写的方法。onCreate(),用于初次使用软件时生成数据库表,可以添加一些应用使用时的一些初始化数据。onUpgrade(),用于更新软件时升级数据库表结构。以上的代码就创建了一个text的数据库文件。里面有一个表user,有username,age两个字段。

Activity

  • 新建一个活动,在onCreate方法中初始化。
        DatabaseHelper databaseHelper = new DatabaseHelper(this);
        //两种,可读的和可写的.磁盘满了之后,就只能读; 。
        mSqLiteDatabase = databaseHelper.getReadableDatabase();

除了gerReadableDatabase(),还有getWriteableDatabase()。两者没有什么区别,只有当磁盘满了之后,就只能读不能写了。当DatabaseHelper对象调用这个方法的时候,如果数据库不存在,android系统会自动生成一个数据库,接着调用onCreate()方法。

  • 然后我们在布局文件中写入三个按钮,分别是增删更



    

在activity中初始化按钮绑定监听器。此时如果启动软件,在/data/data/<包名>/Databases文件下就有我们创建的数据库,如图:


第六章--绕不开的数据库SQLite_第1张图片
这里写图片描述

点开text.db,就有刚刚创建的数据库:


这里写图片描述

这样就是创建好了一个表

数据库操作

  • 首先是增,使用insert插入数据,先看代码
       ContentValues contentValues = new ContentValues();
                contentValues.put(DatabaseHelper.USERNAME , "haha");
                contentValues.put(DatabaseHelper.AGE, "12");

                long rawNumber =  mSqLiteDatabase.insert(DatabaseHelper.USER_TABLE_NAME, null, contentValues);
                if (rawNumber != -1){
                    Toast.makeText(DatabaseButtonActivity.this,"插入成功" ,Toast.LENGTH_LONG).show();
                }

insert()方法里面的参数:

  1. table:想插入数据库的表名
  2. nullColumsnHack:代表强行插入null值的数据列的列名。
  3. valus:代表一行记录的数据

当插入有异常的时候会返回一个long类型的-1值。

  • 然后是删:
String whereClauseString = "username=?";
                String[] whereArgsString = {"haha"};
                mSqLiteDatabase.delete(DatabaseHelper.USER_TABLE_NAME, whereClauseString, whereArgsString);

里面参数的意思就是,在表中username=haha的数据都删除。

  • 更新数据:
ContentValues contentValues1 = new ContentValues();
                contentValues1.put(DatabaseHelper.AGE, "100");
                String whereClauseString1 = "username=?";
                String[] whereArgsString1 = {"haha"};
                mSqLiteDatabase.update(DatabaseHelper.USER_TABLE_NAME,contentValues1, whereClauseString1, whereArgsString1);

这个和insert有点像,都是先用ContentValus对象把存入的数据写好,然后传到updata的参数里,以上代码的意思就是把user表中username=haha的年纪改成100。

  • 最后数据库中的查询操作

在SQLite中查询记录要依靠Cursor(游标),他有一些方法来移动查询结果的记录指针

  1. boolean moveToFirst():将记录指针移到第一行,成功返回true
  2. boolean moveToNext():移动到下一行,当只执行一次的时候,相当与moveToFirst
  3. boolean moveToPosition(int positon):移动到指定行,其实看到这里群里有人提出,moveToNext不是移到了下一个记录了吗?那第一个记录不是没有查询到?然后在这个方法里得到了解释,position默认的值并不是0,而是-1。所以刚开始的指针不是指着第一个记录,而是第一个记录的前面,所以用moveToNext也能查询到第一个记录。

先看代码:

    private void QueryDatabase() {
        //游标
        //query:查询
        Cursor cursor = mSqLiteDatabase.query(DatabaseHelper.USER_TABLE_NAME, null, null, null, null, null, null);
        if (cursor.moveToFirst()){
            int count = cursor.getCount();
            for (int i = 0; i < count; i++) {
                String userName = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.USERNAME));
                String age = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.AGE));
                Log.i(DatabaseButtonActivity.class.getSimpleName(), i + ":" + userName + ":" + age);
                cursor.moveToNext();
            }

        }
        

    }

query里面参数有3种形式,以最多那个来解释一下:

  1. boolean distinct:是否去掉重复的记录
  2. String table:查询数据的表名
  3. String[] columns:查询的列名。相当于select后面的关键字
  4. String whereClause:查询条件子句。where...
  5. String[] selectionArgs:用于为whereClause子句中的占位符传入参数值。
  6. String groupBy:控制分组
  7. String having:分组的过滤
  8. String orderBy:排序
  9. String limit:进行分页

query返回的是Cursor对象,getString()取出某一列的数据。

以上就是数据库的基本操作,但是除了创建表的时候,都没有使用过原始的sql语句,据说android为了考虑不太熟悉数据库语句的人,所以提供了这些方法。我看的这本书的作者一直在吐槽这种做法,说作为程序员,数据库操作应该是最基本的素养。其实我觉得吧,我现在用着挺好的哈哈。可以用execSQL()和rawSQL()方法来执行原始的sql语句,而且效率也要高。

最后,相关的io操作还是不要和我一样放在主线程里,毕竟阻塞主线程是大忌。


这些是老师讲的内容,也没怎么理解,比如什么时候使用事务可以达到效率最大化,先留在这。。

如何设计数据库和表

上万条数据如何建表,比如300个城市,每个城市600条数据,对表进行拆表,比如可以先进行排序,再存入

对数据库进行增删改查

  • 原始SQL语句效率更高rawQuery,execSQL
  • 只检索有用的信息,有用的列,有用的行,越少越好
  • 是否排序
  • 是否创建索引

事务

  • //开始事务,数据库会被锁定
    begainTransaction();
  • //操作
  • ...
  • setTransactionSuccessful();
    endTransaction()

对象关系映射ORM

  • 关系数据库和实体对象进行映射。
  • 优点:方便的进行数据库操作
  • 缺点:效率比较低,不够灵活

你可能感兴趣的:(第六章--绕不开的数据库SQLite)