標籤:android sqlite database
前言
我的部落格:http://mrfufufu.github.io/
最近項目中要用到資料庫,因為之前需要本機存放區的資料量並不是非常大,SharedPreferences 足以解決大部分的資料存放區問題,所以,我們一直沒有用到 SQLite。現在產品需要最佳化私信模組體驗,所以增加私信本機存放區是非常必要的。這時候用上 SQLite 就非常必要了。好在我們的老大之前就已經封裝好了一份非常完善的資料庫架構了,拿來就能用。看了源碼研究了一天,大概有了寫心得體會,整理出來,學習使用。
就給他起名叫 KopDB 吧(Kop 是我們老大打 log 的時候用的 tag),KopDB 採用的是對象關係映射(ORM)的模式,並將我們平時開發時最常用到的一些資料庫功能進行了封裝,使得不用編寫一行SQL語句就可以完成各種建表、増刪改查的操作。
這篇文章主要講的只是 KopDB 的使用,具體分析我會在下篇文章中。
Github 項目地址,裡麵包含了 lib 和對應的 demo,歡迎 Star
https://github.com/MrFuFuFu/KopDB.git
主要的使用方式非常簡單:
先給出 demo 中的資料 model 模型方便後面閱讀理解:
public class PersonModel extends BaseModel { private static final long serialVersionUID = 3462436436344054489L; public static final String PERSON_ID = "person_id"; public static final String PERSON_NAME = "person_name"; public static final String PERSON_AGE = "person_age"; public static final String PERSON_ADDRESS = "person_address"; public static final String PERSON_PHONE = "person_phone"; @DatabaseField(columnName = PERSON_ID, index = true, unique = true, canBeNull = false) public int id; @DatabaseField(columnName = PERSON_NAME) public String name; @DatabaseField(columnName = PERSON_AGE) public String age; @DatabaseField(columnName = PERSON_ADDRESS) public String address; @DatabaseField(columnName = PERSON_PHONE) public String phone; @Override public String toString() { return "id=" + id + "\r name=" + name + "\r age=" + age + "\r address=" + address + "\r phone=" + phone; }}
其中 id 的寫法就表示它是主鍵啦,注意:必須繼承 BaseModel 。
1、初始化:
public void initDB() { if (DatabaseManager.getInstance().isInited()) return; String dbName = "person.db"; int version = 0; try { version = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; } catch (NameNotFoundException e) { e.printStackTrace(); } List<Class<?>> list = new ArrayList<Class<?>>(); list.add(PersonModel.class); DatabaseManager.getInstance().initDataBase(getApplicationContext(), dbName, version, list);}
其中 dbName 就是資料庫名字;version 版本這裡使用的是 versionCode,這樣每次升級版本號碼以後資料庫都會升級一次。當然你也可以自己定義;list 就是需要存到資料庫的映射模型列表,它必須繼承自 BaseModel。初始化完成以後,資料庫和表就都已經給我們建立好了。
根據對象關係映射模式的理念就是每一張表都應該對應一個模型(Model),也就是說,如果我們想要建一張 person 表,就應該有一個對應的 Person 模型類。
2、insert 資料
一行代碼就能搞定:
DatabaseManager.getInstance().insert(PersonModel.class, model);
如果想要監聽插入是否失敗,則可以調用如下 insert 方法
DatabaseManager.getInstance().insert(PersonModel.class, model, new DatabaseManager.getInstance().insert(PersonModel.class, model, new DBOperateAsyncListener() { @Override public <T extends BaseModel> void onPostExecute(DatabaseOptionType optionType, Class<T> claz, List<T> successModels, List<T> failModels) { if (successModels != null) { Log.i("MrFu", "Success = " + ((PersonModel)(successModels.get(0))).toString()); }else if (failModels != null) { Log.i("MrFu", "Fail = " + ((PersonModel)(failModels.get(0))).toString()); } }});
當然,如果我的資料是一個 list 的形式的,也可也直接插入,而不需要寫 for 迴圈一條一條插入,
DatabaseManager.getInstance().insert(PersonModel.class, models);
3、update 資料
同樣也是一行代碼的事情:
DatabaseManager.getInstance().update(PersonModel.class, model1);
他同樣支援4個重載方法,insert 沒有實際給出,這裡給出他的四個重載方法,insert 類似
DatabaseManager.getInstance().update(Class<T> claz, T t);DatabaseManager.getInstance().update(Class<T> claz, List<T> models);DatabaseManager.getInstance().update(Class<T> claz, T t, DBOperateAsyncListener listener);DatabaseManager.getInstance().update(Class<T> claz, List<T> models, DBOperateAsyncListener listener);
4、replace 資料
同樣也是一行代碼就能搞定啦,同樣支援4個重載方法:
DatabaseManager.getInstance().replace(Class<T> claz, T t);DatabaseManager.getInstance().replace(Class<T> claz, List<T> models);DatabaseManager.getInstance().replace(Class<T> claz, T t, DBOperateAsyncListener listener);DatabaseManager.getInstance().replace(Class<T> claz, List<T> models, DBOperateAsyncListener listener);
5、delete 資料
同樣也是喔,其中 whereClause 是 delete 的條件,whereArgs就是 whereClause 的預留位置啦:
DatabaseManager.getInstance().delete(Class<T> claz, String whereClause, String[] whereArgs);DatabaseManager.getInstance().delete(Class<T> claz, String whereClause, String[] whereArgs, DBOperateDeleteListener listener);
舉個例子,刪除 id 為 1 的資料
DatabaseManager.getInstance().delete(PersonModel.class, PersonModel.PERSON_ID + " = ?", new String[] {"1"});
這就表示刪除 PersonModel 表中的 person_id 為 1 的資料。
6、select 資料
如果需要查詢整張表的資料,只需要按照下面的寫法就可以咯:
DatabaseManager.getInstance().select(PersonModel.class, null, null, null, null, null, null, null);
其實這麼寫還是多餘了。所以,我覺得我應該添加這麼個方法:
List<PersonModel> list = DatabaseManager.getInstance().select(PersonModel.class);
這麼來看,就方便多了,如果我需要查詢整張表的資料,直接調用這個方法就可以了,當然如果你想對 select 方法進行擴充的話,完全可以重載更多的 select 方法來進行實現。
其中 SQLiteDateBase 的 query 方法如下,可以根據這個方法的參數對應這來重載 select 方法,參數都是相同的:
/*** Query the given table, returning a {@link Cursor} over the result set.** @param table The table name to compile the query against.* @param columns A list of which columns to return. Passing null will* return all columns, which is discouraged to prevent reading* data from storage that isn‘t going to be used.* @param selection A filter declaring which rows to return, formatted as an* SQL WHERE clause (excluding the WHERE itself). Passing null* will return all rows for the given table.* @param selectionArgs You may include ?s in selection, which will be* replaced by the values from selectionArgs, in order that they* appear in the selection. The values will be bound as Strings.* @param groupBy A filter declaring how to group rows, formatted as an SQL* GROUP BY clause (excluding the GROUP BY itself). Passing null* will cause the rows to not be grouped.* @param having A filter declare which row groups to include in the cursor,* if row grouping is being used, formatted as an SQL HAVING* clause (excluding the HAVING itself). Passing null will cause* all row groups to be included, and is required when row* grouping is not being used.* @param orderBy How to order the rows, formatted as an SQL ORDER BY clause* (excluding the ORDER BY itself). Passing null will use the* default sort order, which may be unordered.* @param limit Limits the number of rows returned by the query,* formatted as LIMIT clause. Passing null denotes no LIMIT clause.* @return A {@link Cursor} object, which is positioned before the first entry. Note that* {@link Cursor}s are not synchronized, see the documentation for more details.* @see Cursor*/public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {...}
怎麼樣,是不是非常簡單呢,我們不需要考慮如何? SQLiteOpenHelper 也不需要考慮那些複雜的 SQL 情況。
這篇部落客要講述的是如何使用 KopDB 架構,下一篇部落格,我會對這個架構的實現進行具體的分析,以加深印象,方便以後的擴充和學習。
本篇文章對 SQLite 的講解不是非常的細緻,有關 SQLite 的詳細說明可以參照這兩篇博文,非常非常詳細:
郭霖: Android資料庫高手秘籍
scott: Android中SQLite應用詳解
Android SQLite, KopDB 架構學習1——使用