• 数据存储与访问之——初见SQLite数据库


       
     

    本节引言:

    本节学习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,1);
        }
    
        //数据库第一次创建时被调用
        @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 = 1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mContext = MainActivity.this;
            myDBOpenHelper = new MyDBOpenHelper(mContext,"my.db",null,1);
            //获取布局的控件
            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 + "
    ");
                        }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[]{"3"});
                    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(0);
        cursor.close();
        return result;      
    }   

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

    本节小结:

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

  • 相关阅读:
    根据一个class,对改class 建一个内表
    将一个内表中的数据,读取到structure中。不用loop循环.
    sap gui中打断点,进入不了断点
    使用python 写一个 股票涨跌提醒功能
    windows使用方法
    mathType插入公式编号,及对公式编号的字体进行修改。调整公式上下间距。
    notefirst使用
    word自动导入目录
    杀死正在运行的进程: linux
    win10系统电脑调节屏幕亮度选项无法显示
  • 原文地址:https://www.cnblogs.com/nylcy/p/5462841.html
Copyright © 2020-2023  润新知