天天看點

Android 資料庫ORM架構GreenDao學習心得及使用總結<二>

轉:http://blog.csdn.net/xushuaic/article/details/24496191

查詢會傳回符合某些特定标準的實體。你可以使用原始的SQL定制查詢語句,或者更好的方式:使用GreenDao的QueryBuilder API。該查詢也支援lazy-loading的結果集。這樣在操作大量結果集的時候可以節省記憶體和性能。
QueryBuilder可以幫助你建構自定義的查詢語句,而不使用SQL的情況。并不是每個人都喜歡書寫SQL語句,當然很容易就會出一些錯,這些錯誤隻有在運作的時候才會被發現。而QueryBuilder很容易使用,節省了你書寫SQL語句的時間。當然,由于文法的檢驗是在編譯時才執行,是以在查詢語句中發現bug是很困難的。 QueryBuilder的編譯時間會檢驗屬性的引用,這樣能夠在greenDao後面,通過代碼生成的方法發現bug。
比如:查找所有以“Joe”為first name 的使用者,并以last name排序:

List joes = userDao.queryBuilder()  

.where(Properties.FirstName.eq("Joe"))  

.orderAsc(Properties.LastName)  

.list();  

嵌套情況:

擷取使用者名字為“Joe”并且在1970年9月之後出生的使用者
這裡要說明下:user 的birthday對于year,month,和day是一個分離的屬性。我們可以以一種更正常的方式表達這種條件: First name is “Joe” AND (year of birth is greater than 1970 OR (year of birth is 1970 AND month of birth is equal to or greater than 10 (October).

QueryBuilder qb = userDao.queryBuilder();  

qb.where(Properties.FirstName.eq("Joe"),  

qb.or(Properties.YearOfBirth.gt(1970),  

qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));  

List youngJoes = qb.list();  

Query類代表一個可以多次執行的查詢。當你使用QueryBuilder之一的方法去擷取結果的時候,QueryBuilder内部使用了Query 類。 如果你想運作更多相同的查詢,你應該調用build()在QueryBuilder上,去建立Query,而不是執行它。
greenDao支援唯一的結果和結果清單。如果你想得到一個唯一的結果,可以調用Query或者QueryBuilder的unique()方法,這樣在沒有比對條件的時候會傳回一個唯一的結果,而不是null。如果你希望禁止用例中傳回null,可以調用uniqueOrThrow(),該方法會保證傳回一個非null的實體。否則就會抛出一個DaoException。
如果你期望一次性傳回多個實體,可以使用以下方法: list():所有的實體被加載到記憶體中。該結果通常是一個沒有magic involved的ArrayList。使用起來最簡單。 listLazy():實體按照需求加載進入記憶體。一旦清單中的一個元素被第一次通路,它将被加載同時緩存以便以後使用。必須close。 ListLasyUncached(): 一個“虛拟”的實體清單:任何對清單元素的通路都會導緻從資料庫中加載,必須close。 listIterator(): 周遊通過需要的時候加載(lazily)獲得的結果,資料沒有緩存,必須close。
listLazy, listLazyUncached 和 listIterator類使用了greenDao的LazyList類。為了根據需求加載資料,它持有了一個資料庫cursor的引用。 這是做是為了確定關閉 lazy list和iterators(通常在try/finally 代碼塊中)。 一旦有的元素被通路或者周遊過,來自lsitLazy()的cache lazy list和來自listIterator()方法的lazy iterator将會自動關閉cursor。 然而,如果list的處理過早的完成了,你應該調用 close()手動關閉。
一旦你使用QueryBuilder建構了一個query,該query對象以後可以被重複使用。這種方式比總是重複建立query對象要高效。 如果query的參數沒有變更,你隻需要再次調用list/unique方法即可。如果有參數變更,你就需要調用setParameter方法處理每一個變更的參數。 現在,個别參數由基于零的參數索引尋址。該下标基于你傳遞到querybuilder的參數。

使用query對象擷取出生在1970年 并且 first name 為 joe 的使用者:

Query query = userDao.queryBuilder().where(  

Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))  

.build();  

List joesOf1970 = query.list();  

使用query對象,可以查詢

query.setParameter(0, "Maria");  

query.setParameter(1, 1977);  

List mariasOf1977 = query.list();  

如果你在多線程中使用了查詢,你必須調用query的 forCurrentThread()為目前的線程獲得一個query執行個體。從greenDAO 1.3開始, query的執行個體化被綁定到了那些建立query的線程身上。這樣做保證了query對象設定參數時的安全性,避免其他線程的幹擾。如果其他線程 試着在query對象上設定參數或者執行查詢綁定到了其它線程,将會抛出異常。這樣一來,你就不需要一個同步語句了。 事實上你應該避免使用lock,因為如果在并發的事務中使用了同一個query對象,可能會導緻死鎖。
為了完全避免那些潛在的死鎖問題,greenDAO 1.3 引入了forCurrentThread方法,它會傳回一個query對象的thread—local執行個體,該執行個體 在目前的線程中使用是安全的。當每一次調用 forCueerntThread()的時候,該參數會在builder建構query的時候,設定到初始化參數上。
這裡有兩種方式執行原始的SQL去擷取實體。較好的一種方式是使用QueryBuilder 和 WhereCondition.StringCondition。 使用這個方法,你可以為 query builder 的 WHERE 子句傳遞任何SQL片段。 下面是一個笨拙的例子展示如果使用這種方式進行一個替代聯合查詢的子查詢。

new StringCondition("_ID IN " +  

"(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)").build();  

該示例中query Builder沒有提供你需要的特性,你可以回到原始的queryRaw或者queryRawCreate方法。它們允許你傳遞原始的SQL字元串,這些字元串會被添加到SELECT 和實體列後面。這種方式,你可以擁有一個 WHERE 和 ORDER BY 語句查詢實體。這種實體表可以通過别名“T”引用。

下面的例子展示了如何建立一個query:使用聯合擷取名為“admin”的group的users

Query query = userDao.queryRawCreate(  ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin");  

提示: 你可以通過生成的常量引用表或者列名。這樣建議是為了避免錯别字,因為編譯器會檢驗這些名字。在任何實體的DAO,你可以發現 TABLENAME 持有着資料庫的名字和一個内部類“Properties”.它的所有屬性都是常量。
批量删除不删除單獨的實體,但所有的實體要比對一些準則。為了執行批量删除,建立一個QueryBuilder,調用它的buildDelete方法,它會傳回一個DeleteQuery。 這部分的API可能會在以後有所變化,比如添加一些更加便利的方法。記住,批量删除現在不會影響到identity scope中的實體。在它們被通過ID通路之前(load 方法) 如果它們被緩存了,你可以激活那些将要被删除的實體。如果導緻了一些使用的問題。你可以考慮清除identity scope。
如果你的query沒有傳回期望的結果,這裡有兩個靜态的flag,可以開啟QueryBuilder身上的SQL和參數的log。
Android 資料庫ORM架構GreenDao學習心得及使用總結<二>
QueryBuilder.LOG_SQL = true;   QueryBuilder.LOG_VALUES = true;  
它們會在任何build方法調用的時候列印出SQL指令和傳入的值。這樣你可以對你的期望值進行對比,或許也能夠幫助你複制SQL語句到某些 SQLite 資料庫的檢視器中,執行并擷取結果,以便進行比較。