1. 程式人生 > >Android-GreenDao增刪改查以及底層實現簡介

Android-GreenDao增刪改查以及底層實現簡介

GreenDao 初始化:

public voidinitDB(Context context,String dbName)

{

this.context= context;

DaoMaster.DevOpenHelper helper =newDaoMaster.DevOpenHelper(context,"name_jia_"+ dbName, null);

instance.sqlDb= helper.getWritableDatabase();

instance.cx_jia_daoMaster=newDaoMaster(instance.sqlDb);

instance.cx_jia_daoSession=instance.cx_jia_daoMaster.newSession();

}

這個程式碼主要是用於建立資料庫和初始化一些變數,如初始化NoteDao的父類AbstractDao的變數和引數,

protected final SQLiteDatabase db;

protected final DaoConfig config;

protected IdentityScope identityScope;

protected IdentityScopeLong identityScopeLong;

protected TableStatements statements;

protected final AbstractDaoSession session;

protected final int pkOrdinal;

注意:

SQLiteDatabase db:我們建立的資料庫物件;

DaoConfig config:用於儲存資料訪問物件Dao的基本資料;

TableStatements statements:用於生成操作資料表的SQL statements;

identityScope:greendao有一個快取機制,即把使用者插入,更改或查詢的實體儲存在記憶體中,當用戶下一次查詢時先從記憶體中查詢

,如果不存在再從資料庫中查詢,當表的主鍵是數字型別的時候,identityScopeLong將不會空,並且指向identityScope。

在初始每個dao物件的DaoConfig的時候,判斷主鍵是否是數字型別,

主鍵初始化:


如果主鍵是數字型別的話,initIdentityScope時identityScope 初始化IdentityScopeLong型別,

然後在資料操作物件的父類(AbstractDao)的構造方法中,將identityScopeLong 指向identityScope,之後我們只需要extends就可以了,如下圖


然後,所有主鍵為數字型別dao物件獲取記憶體中快取物件的都會呼叫IdentityScopeLong中的get方法


所以,如果主鍵不是long型別的話就會報型別轉換錯誤!

我們可以自己控制是否使用快取功能,在DaoMaster中有兩個初始化DaoSession的方法,我們可以使用第二個構造方法並傳入type為IdentityScopeType.None,這樣initIdentityScope方法就會包identityScope 賦為空值,即不使用快取機制。

再次強調:在使用greendao快取機制的情況下,如果資料表的主鍵是數字型別的話,一定要使用long型別,不然不會報型別轉換錯誤。。大家可以去實踐下

好進入正題:

1)插入物件(insert):

User user= new User("id","name");

getUserDao().insert(user);

底層程式碼如下:


首先判斷資料庫是否被當前執行緒鎖住,如果是,繫結引數並執行插入,如果不是,則開啟一個事務,然後繫結引數並執行插入。

其中,UserDao重寫了父類AbstractDao的bindValues方法,進行相對應物件資料的繫結,

updateKeyAfterInsertAndAttach(entity, rowId, true)是為了更新自增主鍵的id,將實體放入快取中。

(當然還有insertOrReplace ,他們直接的區別大家自己動手去研究,可以說從字面上理解就好了。深層次上的理解就得從sql語句了)

2)刪除物件delete:

userDao.deleteByKey(id)

底層實現程式碼如下:



刪除物件與插入物件相似,刪除操作目前僅支援操作單一主鍵的表,assertSinglePk()是判斷物件是否是單一主鍵,若不是則丟擲錯誤。

往往我們要的是根據某個欄位進行刪除,如下

public void deleteMsgByUserName(String username) {

userDao.queryBuilder().where(UserDao.Properties.Username.eq(username)).buildDelete().executeDeleteWithoutDetachingEntities();

}

3)更改物件update:

userDao.update(user)

底層程式碼實現:


具體也是和新增,刪除一樣,先判斷執行緒,然後再判斷主鍵id。

當然我們也可以使用之前說的insertOrReplace,進行更新,底層程式碼和新增一樣,區別在



Stringsql = SqlUtils.createSqlInsert("INSERT OR REPLACE INTO ",tablename,allColumns);

SQLiteStatement newInsertOrReplaceStatement =db.compileStatement(sql);

在編譯時候到底是Inert 還是replace..

4)查詢 


查詢物件的實現實現是原理是傳入多個限制條件,然後在底層程式碼中拼接sql查詢語句進行查詢,然後在轉換成相對應的物件。查詢的機制跟其他操作方式一樣,如果有使用greendao的快取機制,則先從快取中獲取,再從資料庫獲取,如果沒有使用快取機制,則直接從資料庫中獲取。

如果需要使用更復雜的查詢方法的話,可以檢視Property類和QueryBuilder的原始碼,greendao提供多種方式的拼接,可以組成日常開發中經常用到的查詢語句。

需要一提的是greendao的懶載入功能。這個以後再說。



文/kecai(簡書作者)
原文連結:http://www.jianshu.com/p/5681e183926d
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。