天天看點

Android-SQLite的CRUD

将資料儲存到資料庫對于重複或結構化資料而言是理想之選。 本課程假定您基本熟悉 SQL 資料庫并且可幫助您開始在 Android 中使用 SQLite 資料庫。 您在 Android 中使用資料庫所需的 API 在 android.database.sqlite 包中提供。

定義schema和contract

SQL 資料庫的主要原則之一是schema:資料庫如何組織的正式聲明。 schema展現于您用于建立資料庫的 SQL 語句。您會發現它有助于建立伴随類,即contract類,其以一種系統性、自記錄的方式明确指定您的schema布局。

contract類是用于定義 URI、table和列名稱的常數的容器。 contract類允許您跨同一軟體包中的所有其他類使用相同的常數。 您可以在一個位置更改列名稱并使其在您整個代碼中傳播。

組織contract類的一種良好方法是将對于您的整個資料庫而言是全局性的定義放入類的根級别。 然後為枚舉其列的每個表格建立内部類。

注:通過實作 BaseColumns 接口,您的内部類可繼承名為 _ID 的主鍵字段,某些 Android 類(比如光标擴充卡)将需要内部類擁有該字段。 這并非必需項,但可幫助您的資料庫與 Android 架構協調工作。

例如,該代碼段定義了單個表格的表格名稱和列名稱:

public final class FeedReaderContract {
    // To prevent someone from accidentally instantiating the contract class,
    // make the constructor private.
    private FeedReaderContract() {}

    /* Inner class that defines the table contents */
    public static class FeedEntry implements BaseColumns {
        public static final String TABLE_NAME = "entry";
        public static final String COLUMN_NAME_TITLE = "title";
        public static final String COLUMN_NAME_SUBTITLE = "subtitle";
    }
}
           

使用 SQL Helper建立資料庫

在您定義了資料庫的外觀後,您應實作建立和維護資料庫和表格的方法。 這裡有一些典型的表格建立和删除語句:

private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
    "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
    FeedEntry._ID + " INTEGER PRIMARY KEY," +
    FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
    FeedEntry.COLUMN_NAME_SUBTITLE + TEXT_TYPE + " )";

private static final String SQL_DELETE_ENTRIES =
    "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
           

就像您在裝置的内部存儲中儲存檔案那樣,Android 将您的資料庫儲存在私人磁盤空間,即關聯的應用。 您的資料是安全的,因為在預設情況下,其他應用無法通路此區域。

SQLiteOpenHelper 類中有一組有用的 API。當您使用此類擷取對您資料庫的引用時,系統将隻在需要之時而不是應用啟動過程中執行可能長期運作的操作:建立和更新資料庫。 您僅需調用 getWritableDatabase() 或 getReadableDatabase() 即可。

注:由于它們可能長期運作,是以請確定您在背景線程中調用 getWritableDatabase() 或 getReadableDatabase(),比如使用 AsyncTask 或 IntentService。

要使用 SQLiteOpenHelper,請建立一個替換 onCreate()、onUpgrade() 和onOpen() 回調方法的子類。您可能還希望實作 onDowngrade(),但這并非必需操作。

例如,下面是一個使用如上所示一些指令的 SQLiteOpenHelper 的實作:

public class FeedReaderDbHelper extends SQLiteOpenHelper {
    // If you change the database schema, you must increment the database version.
    public static final int DATABASE_VERSION = ;
    public static final String DATABASE_NAME = "FeedReader.db";

    public FeedReaderDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_ENTRIES);
    }
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // This database is only a cache for online data, so its upgrade policy is
        // to simply to discard the data and start over
        db.execSQL(SQL_DELETE_ENTRIES);
        onCreate(db);
    }
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }
}
           

要通路您的資料庫,請執行個體化 SQLiteOpenHelper 的子類:

将資訊存入資料庫

通過将一個 ContentValues 對象傳遞至 insert() 方法将資料插入資料庫:

// Gets the data repository in write mode
SQLiteDatabase db = mDbHelper.getWritableDatabase();

// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle);

// Insert the new row, returning the primary key value of the new row
long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);
           
  • 參數
  • insert() 的第一個參數即為表名稱。
  • 第二個參數将訓示架構在 ContentValues 為空(即,您沒有傳任何值)時執行哪些操作。如果指定列名稱,則架構将插入一行并将該列的值設定為 null。如果指定 null(就像此代碼示例中一樣),則架構不會在沒有值時插入行。

從資料庫讀取資訊

要從資料庫中讀取資訊,請使用 query() 方法,将其傳遞至選擇條件和所需列。該方法結合 insert() 和 update() 的元素,除非列 清單定義了您希望擷取的資料,而不是希望插入的資料。 查詢的結果将在 Cursor 對象中傳回給您。

SQLiteDatabase db = mDbHelper.getReadableDatabase();

// Define a projection that specifies which columns from the database
// you will actually use after this query.
//projection是投影的意思,這裡意為選擇哪些列的資料
String[] projection = {
    FeedEntry._ID,
    FeedEntry.COLUMN_NAME_TITLE,
    FeedEntry.COLUMN_NAME_SUBTITLE
    };

// Filter results WHERE "title" = 'My Title'
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };

// How you want the results sorted in the resulting Cursor
String sortOrder =
    FeedEntry.COLUMN_NAME_SUBTITLE + " DESC";

Cursor c = db.query(
    FeedEntry.TABLE_NAME,                     // The table to query
    projection,                               // The columns to return
    selection,                                // The columns for the WHERE clause
    selectionArgs,                            // The values for the WHERE clause
    null,                                     // don't group the rows
    null,                                     // don't filter by row groups
    sortOrder                                 // The sort order
    );
           

要檢視遊标中的某一行,請使用 Cursor 其中一個移動方法,您必須在開始讀取值之前始終調用這些方法。 一般情況下,您應通過調用 moveToFirst() 開始,其将“讀取位置”置于結果中的第一個條目中。 對于每一行,您可以通過調用 Cursor 擷取其中一個方法讀取列的值,比如 getString() 或 getLong()。對于每種擷取方法,您必須傳遞所需列的索引位置,您可以通過調用 getColumnIndex() 或 getColumnIndexOrThrow() 擷取。例如:

cursor.moveToFirst();
long itemId = cursor.getLong(
    cursor.getColumnIndexOrThrow(FeedEntry._ID)
);
           

從資料庫中删除資訊

要從表格中删除行,您需要提供識别行的選擇條件。 資料庫 API 提供了一種機制,用于建立防止 SQL 注入的選擇條件。 該機制将選擇規範劃分為選擇子句和選擇參數。 該子句定義要檢視的列,還允許您合并列測試。 參數是根據捆綁到子句的項進行測試的值。由于結果并未按照與正常 SQL 語句相同的方式進行處理,它不受 SQL 注入的影響。

// Define 'where' part of query.
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
// Specify arguments in placeholder order.
String[] selectionArgs = { "MyTitle" };
// Issue SQL statement.
db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs);
           

更新資料庫

當您需要修改資料庫值的子集時,請使用 update() 方法。

更新表可将 insert() 的内容值文法與 delete() 的 where 文法相結合。

SQLiteDatabase db = mDbHelper.getReadableDatabase();

// New value for one column
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);

// Which row to update, based on the title
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { "MyTitle" };

int count = db.update(
    FeedReaderDbHelper.FeedEntry.TABLE_NAME,
    values,
    selection,
    selectionArgs);