【Android】資料儲存(三) 資料庫(SQLite)

weixin_34247155發表於2016-05-31
SQLite

前言

之前介紹過Android中儲存資料的兩種方式:SharedPreferencesFile,這篇介紹另一種儲存資料的方式——資料庫。

資料庫:簡單來說可視為電子化的檔案櫃——儲存電子檔案的處所,使用者可以對檔案中的資料執行新增、擷取、更新、刪除等操作

想必大家對資料庫都不陌生,想當年上資料庫課的時候,被那些命令整得不要不要的。

扯遠了...

進入正題,在Android開發的過程中,儲存資料是難免的。如果資料量較小的時候可用SharedPreferencesFile來儲存,當資料量較大且關係複雜的時候就要用到Android中的資料庫SQLite——輕量級資料庫系統。

用法

舉一個儲存使用者資訊的栗子:
建立一個資料庫mySQLite,在該資料庫中建立一個user表,用來儲存使用者資訊,使用者屬性name(姓名:String型別)、age(年齡:int型別)。

建立一個使用者類(方便後面的操作)

/**
 * 使用者
 * Created by Gavin on 2016/5/30.
 */
public class User {
    /**
     * id
     */
    private int id;
    /**
     * 使用者名稱
     */
    private String name;
    /**
     * 年齡
     */
    private int age;
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

建立一個DatabaseHelper類

用來處理所有的資料庫操作。(這用到了SQL語句,不懂的看解釋)

/**
 * Created by Gavin on 2016/5/30.
 */
public class DatabaseHelper extends SQLiteOpenHelper {
    /**
     * 資料庫版本,需要升級資料庫時只要加一即可
     */
    private static final int DATABASE_VERSION = 1;
    /**
     * 資料庫名
     */
    private static final String DATABASE_NAME = "mySQLite.db";

    /**
     * 構造方法
     * 每次建立DatabaseHelper物件時,若本應用無該資料庫,則新建資料庫並呼叫onCreate方法;
     * 若該資料庫已建立則直接使用已存在的資料庫且跳過onCreate方法
     * @param context   上下文
     */
    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /**
     * 建立資料庫是時呼叫(只被呼叫一次)
     * @param db    資料庫
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        //建立user表,屬性:id(使用者id,主鍵)、name(姓名)、age(年齡)
        db.execSQL("CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(10),age INTEGER)");
    }

    /**
     * 跟新資料庫時呼叫
     * @param db            資料庫
     * @param oldVersion    舊版本號
     * @param newVersion    新版本號
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //升級:往user表,新增性別屬性
        //db.execSQL("ALTER TABLE user ADD COLUMN gender VARCHAR(2)");
    }
}

資料庫mySQLite在構造方法中建立,其中super()的引數有4個:
context:上下文;
datebaseName:資料庫名,一般以.db結尾;
factory : 當開啟的資料庫執行查詢語句的時候 會建立一個Cursor物件, 這時會呼叫Cursor工廠類 factory, 可以填寫null預設值;
version:資料庫版本,需要升級資料庫時將版本號加一,將升級的內容寫在onUpgrade中即可。

  • onCreate
    當資料庫第一次建立的時候,會執行onCreate()方法。這裡的onCreate方法中建立了一張user表,db.execSQL()方法執行了裡面SQL語句。
  • onUpgrade
    資料庫升級時會呼叫onUpgrade()方法,這裡的onUpgrade()方法往user表中新增了性別(gender)屬性。

運算元據庫

運算元據庫,增刪查改是免不了的。下面的方法都是在DatabaseHelper 中新增。

  • 增(Create)
    /**
     * 插入一條資料
     * @param user  使用者物件
     */
    public void insertAUser(User user) {
        //如果要對資料進行更改,就呼叫此方法得到用於運算元據庫的例項,
        //該方法以讀和寫方式開啟資料庫
        SQLiteDatabase database = getWritableDatabase();
        //向user表插入一條資料
        database.execSQL(
                "INSERT INTO user(name, age) VALUES(?,?)",
                new Object[]{user.getName(), user.getAge()});
    }

insertAUser()中使用了execSQL()執行了插入資料的操作。
這裡用到的execSQL()有兩個引數:
引數1:SQL指令,這裡是一條插入命令,命令中的問號(?)為佔位符
引數2:Object陣列,陣列中的內容對應引數1中的問號(?)

  • 刪(Delete)
    /**
     * 根據id刪除一條資料
     * @param id    使用者id
     */
    public void deleteAUser(Integer id) {
        SQLiteDatabase database = getWritableDatabase();
        //根據id刪除一條資料
        database.execSQL("DELETE FROM user WHERE id=?",
                new Object[]{id});
    }

deleteAUser()根據使用者id,刪除了對應的使用者資訊。這裡也是用了execSQL()執行資料操作。

  • 查(Read)
    /**
     * 讀取一條資料
     * @param id    使用者id
     * @return      使用者物件
     */
    public User readAUser(Integer id) {

        //如果只對資料進行讀取,建議使用此方法
        SQLiteDatabase database = getReadableDatabase();
        Cursor cursor  = database.rawQuery(
                "SELECT * FROM user WHERE id=?",
                new String[]{id.toString()});
        if (cursor.moveToFirst()) {
            //讀取資料,並返回
            User user = new User();
            user.setId(cursor.getInt(cursor.getColumnIndex("id")));
            user.setName(cursor.getString(cursor.getColumnIndex("name")));
            user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
            cursor.close();
            return user;
        } else {
            //未讀出資料,返回空資料
            return null;
        }
    }

    /**
     * 獲取整個使用者列表
     * @return
     */
    public List<User> readAllUser() {
        SQLiteDatabase database = getReadableDatabase();
        Cursor cursor = database.rawQuery("SELECT * FROM user", new String[]{});
        List<User> list = new ArrayList<User>();
        //使用moveToNext()逐條讀取
        while (cursor.moveToNext()) {
            User user = new User();
            user.setId(cursor.getInt(cursor.getColumnIndex("id")));
            user.setName(cursor.getString(cursor.getColumnIndex("name")));
            user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
            list.add(user);
        }
        cursor.close();
        return list;
    }

readAUser()中使用rawQuery方法獲取到使用者資訊,通過cursor.moveToFirst()來獲取cursor的第一條資料,接著通過cursor.getInt()、cursor.getString()來獲取對應的資料。

這裡使用了getReadableDatabase()而不是getWritableDatabase()

  • 改(Update)
    /**
     * 更新一條使用者資料
     * @param user  使用者物件
     */
    public void updateAUser(User user) {
        SQLiteDatabase database = getWritableDatabase();
        //根據id更新一條資料
        database.execSQL(
                "UPDATE user SET name=?, age=? WHERE id=?",
                new Object[]{user.getName(), user.getAge(), user.getId()});
    }

這也沒什麼好說的~~

execSQL()中用到的都最基礎的是SQL指令,至於複雜的自己去查吧

使用

輔助類DatabaseHelper寫完了,接下來就是使用了

  • 插入一條資料
        DatabaseHelper helper = new DatabaseHelper(this);
        User user1 = new User();
        user1.setName("lisa");
        user1.setAge(20);
        helper.insertAUser(user1);//插入一條資料

        Log.i(TAG, helper.readAllUser().toString());//檢視所有使用者

結果


1638147-77b68cc5d9a2f77d.png
結果
  • 根據id獲取一條資料,修改,刪除。上面我們看到,插入的那條資料id是1
        DatabaseHelper helper = new DatabaseHelper(this);
        User user1 = helper.readAUser(1);           //查詢id為1的使用者
        Log.i(TAG, helper.readAUser(1).toString()); //顯示id為1的使用者
        user1.setAge(30);                           //將年齡改為30
        helper.updateAUser(user1);                  //更新資料庫
        Log.i(TAG, helper.readAUser(1).toString()); //顯示id為1的使用者
        helper.deleteAUser(user1.getId());          //刪除user1
        Log.i(TAG, helper.readAUser(1).toString()); //顯示id為1的使用者

結果


1638147-b722bbf52c9576d6.png
結果

上面的程式碼中,分別列印了三次log。
第一次使用id為1的使用者;
第二次是年齡被修改為30的使用者;
第三次是被刪除的使用者,因為使用者不存在了,所以沒有第三條log
(由於helper.readAUser(1)沒有獲取到資料,返回null,接著使用了toString()出現空指標異常,閃退了,做了一個反面教材~~)。
不管怎麼說,這次的目的達到了,增刪查改都ok了。

小結

使用SQLite就是在本地建了一個資料庫,使用資料庫中的表來儲存資料。SQLite對資料的操作十分靈活,不過相比SharedPreferencesFile在使用上要複雜一些,而且要一點的資料庫基礎。

附:DatabaseHelper完整程式碼

package com.nostra13.universalimageloader.sample;

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

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Gavin on 2016/5/30.
 */
public class DatabaseHelper extends SQLiteOpenHelper {
    /**
     * 資料庫版本,需要升級資料庫時只要加一即可
     */
    private static final int DATABASE_VERSION = 1;
    /**
     * 資料庫名
     */
    private static final String DATABASE_NAME = "mySQLite.db";

    /**
     * 構造方法
     * 每次建立DatabaseHelper物件時,若本應用無該資料庫,則新建資料庫並呼叫onCreate方法;
     * 若該資料庫已建立則直接使用已存在的資料庫且跳過onCreate方法
     * factory : 當開啟的資料庫執行查詢語句的時候 會建立一個Cursor物件, 這時會呼叫Cursor工廠類 factory, 可以填寫null預設值
     * @param context   上下文
     */
    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /**
     * 建立資料庫是時呼叫(只被呼叫一次)
     * @param db    資料庫
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        //建立user表,屬性:id(使用者id,主鍵)、name(姓名)、age(年齡)
        db.execSQL("CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(10),age INTEGER)");
    }

    /**
     * 跟新資料庫時呼叫
     * @param db            資料庫
     * @param oldVersion    舊版本號
     * @param newVersion    新版本號
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //升級user表,新增性別
        //db.execSQL("ALTER TABLE user ADD COLUMN gender VARCHAR(2)");
    }

    /**
     * 插入一條資料
     * @param user  使用者物件
     */
    public void insertAUser(User user) {
        //如果要對資料進行更改,就呼叫此方法得到用於運算元據庫的例項,該方法以讀和寫方式開啟資料庫
        SQLiteDatabase database = getWritableDatabase();
        //向user表插入一條資料
        database.execSQL(
                "INSERT INTO user(name, age) VALUES(?,?)",
                new Object[]{user.getName(), user.getAge()});
    }

    /**
     * 更新一條使用者資料
     * @param user  使用者物件
     */
    public void updateAUser(User user) {
        SQLiteDatabase database = getWritableDatabase();
        //根據id更新一條資料
        database.execSQL(
                "UPDATE user SET name=?, age=? WHERE id=?",
                new Object[]{user.getName(), user.getAge(), user.getId()});
    }

    /**
     * 根據id刪除一條資料
     * @param id    使用者id
     */
    public void deleteAUser(Integer id) {
        SQLiteDatabase database = getWritableDatabase();
        //根據id刪除一條資料
        database.execSQL("DELETE FROM user WHERE id=?",
                new Object[]{id});
    }

    /**
     * 獲取整個使用者列表
     * @return
     */
    public List<User> readAllUser() {
        SQLiteDatabase database = getReadableDatabase();
        Cursor cursor = database.rawQuery("SELECT * FROM user", new String[]{});
        List<User> list = new ArrayList<User>();
        while (cursor.moveToNext()) {
            User user = new User();
            user.setId(cursor.getInt(cursor.getColumnIndex("id")));
            user.setName(cursor.getString(cursor.getColumnIndex("name")));
            user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
            list.add(user);
        }
        cursor.close();
        return list;
    }

    /**
     * 讀取一條資料
     * @param id    使用者id
     * @return      使用者物件
     */
    public User readAUser(Integer id) {

        //如果只對資料進行讀取,建議使用此方法
        SQLiteDatabase database = getReadableDatabase();
        Cursor cursor  = database.rawQuery(
                "SELECT * FROM user WHERE id=?",
                new String[]{id.toString()});
        if (cursor.moveToFirst()) {
            //讀取資料,並返回
            User user = new User();
            user.setId(cursor.getInt(cursor.getColumnIndex("id")));
            user.setName(cursor.getString(cursor.getColumnIndex("name")));
            user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
            cursor.close();
            return user;
        } else {
            //未讀出資料,返回空資料
            return null;
        }
    }
}

相關文章