GreenDao3+ 介紹

簡介
GreenDao可以說是當今最流行谁撼,最高效而且還在迭代的關(guān)系型數(shù)據(jù)庫。
關(guān)系型數(shù)據(jù)庫:ORM(Object Relation Mapping 即 對象關(guān)系映射)狞甚,就是將面向?qū)ο缶幊陶Z言里的對象與數(shù)據(jù)庫關(guān)聯(lián)起來的一種技術(shù)及志,greenDao其實就是一種將java object 與SQLite Database關(guān)聯(lián)起來的橋梁

配置不介紹了,參考官網(wǎng)即可加袋。

優(yōu)點

1.存取速度快
2.支持數(shù)據(jù)庫加密
支持android原生的數(shù)據(jù)庫SQLite,也支持SQLCipher(在SQLite基礎(chǔ)上加密型數(shù)據(jù)庫)抱既。
3.輕量級
greenDao的代碼庫僅僅100k大小
4.激活實體
處于激活狀態(tài)下的實體可以有更多操作方法
5.支持緩存
能夠?qū)⑹褂玫倪^的實體存在緩存中职烧,下次使用時可以直接從緩存中取,這樣可以使性能提高N個數(shù)量級
6.代碼自動生成

DaoMaster

DaoMaster 是入口類防泵,每一個DaoMaster持有一個數(shù)據(jù)庫連接蚀之,通過DaoMaster#newSession()方法可以實例化多個Session,這些Session對應(yīng)同一個數(shù)據(jù)庫連接捷泞,但是系統(tǒng)會為每一個Session分配內(nèi)存足删,在這片內(nèi)存中會為實體進行緩存。每一個Session對應(yīng)一個Identity .

DaoSession

從DaoSession中可以獲取各實體類的對應(yīng)DAO锁右,然后就可以進行增刪改查的操作了失受,對于每一個Session中的查詢操作都會對查到的實體類做緩存操作,所以對應(yīng)同一個Session的多次查詢操作咏瑟,如果entity的對象在該Session中有對應(yīng)緩存則直接使用拂到,而不再從數(shù)據(jù)庫中讀取數(shù)據(jù)并構(gòu)建新的實體類對象。

常用注解介紹

@Entity

該實例是類的注解码泞,告訴greenDAO這個類是需要持久化的實體類兄旬。下面是其內(nèi)部注解

@Entity(
        // If you want to have more than one schema, you can tell greenDAO
        // to which schema an entity belongs (pick any string as a name).
        schema = "myschema",
        
        // Flag to make an entity "active": Active entities have update,
        // delete, and refresh methods.
        active = true,
        
        // Specifies the name of the table in the database.
        // By default, the name is based on the entities class name.
        nameInDb = "AWESOME_USERS",
        
        // Define indexes spanning multiple columns here.
        indexes = {
                @Index(value = "name DESC", unique = true)
        },
        
        // Flag if the DAO should create the database table (default is true).
        // Set this to false, if you have multiple entities mapping to one table,
        // or the table creation is done outside of greenDAO.
        createInDb = false
)
@ID, field注解

表示選擇一個long或Long類型的屬性作為該實體所對應(yīng)數(shù)據(jù)庫中數(shù)據(jù)表的主鍵,參數(shù)可以設(shè)置(autoincreament=true),其實其他類型高版本也是可以的余寥,比如String 不過應(yīng)該不能自增長了领铐。

@Property field 注解

可以自定義該屬性在數(shù)據(jù)表的列名悯森,默認的列名為屬性名大寫,并由下劃線隔開多個單詞罐孝,@Property(nameInDb="XXXX")可以自定義列名呐馆。

@NotNull

對應(yīng)著數(shù)據(jù)表中該列不能為空。

@Transient

與Java中的Transient關(guān)鍵字類似莲兢,指不對該屬性持久化汹来,即不為該屬性在數(shù)據(jù)表中創(chuàng)建相應(yīng)列。

@Index

使用@Index 可以將一個屬性變?yōu)閿?shù)據(jù)庫索引改艇;其有倆個參數(shù)
name :不使用默認名稱收班,自定義索引名稱
unique : 給索引增加一個唯一約束,迫使該值唯一

@Entity
public class User { 
@Id 
private Long id;
 @Index(unique = true)
 private String name;
}
@Unique

含義與數(shù)據(jù)表中列的unique一致, 這種情況下谒兄,SQLite會自動為該列建立索引摔桦。

@Generated greenDAO

會根據(jù)開發(fā)者定義的實體類定義schema,并生成DAOs,而在生成過程中會為開發(fā)者編寫的實體類的一些方法和域上添加

@Generated注解

提示開發(fā)者該屬性不能被修改承疲;并且實體類的方法邻耕,屬性,構(gòu)造器一旦被@Generated注釋就不能被再次修改燕鸽,否則或報錯

此外還有@ToOne, @ToMany, @JoinEntity與多個數(shù)據(jù)表的關(guān)系有關(guān)兄世,后面再對此詳細介紹。

@Entity
public class User { 
      @Id(autoincrement = true)
       private Long id;  
      @Property(nameInDb = "USERNAME") 
       private String name;  
      @NotNull 
      private int repos;  
      @Transient 
      private int tempUsageCount; 
 ...}
查詢list

1.list()
緩存查詢結(jié)果;list()類型一般為ArrayList
2.listLazy();
懶查詢,只有當調(diào)用list()中的實體對象時才會執(zhí)行查詢操作并且只緩存第一次被查詢的結(jié)果啊研,需要關(guān)閉
3.listlazyUncached() 懶查詢,只有當調(diào)用list()中的實體對象時才會執(zhí)行查詢操作并且不緩存;
4.listIterator() 對查詢結(jié)果進行遍歷御滩,不緩存,需要關(guān)閉;

   List<City>  cityList =EntityManager.getInstance().getCityDao().queryBuilder().list();
    LazyList<City>  cityList2 =EntityManager.getInstance().getCityDao().queryBuilder().listLazy();
    cityList2.close();
    List<City>  cityList3 =EntityManager.getInstance().getCityDao().queryBuilder().listLazyUncached();
    CloseableListIterator<City> cityList4 =EntityManager.getInstance().getCityDao().queryBuilder().listIterator();
    cityList4.close();//需要try

分頁查詢

limit(int): 限制查詢的數(shù)量;
offset(int): 每次返回的數(shù)量; offset不能單獨使用党远;

多次查詢:

即 第一次查詢返回的 query 可以再次設(shè)置條件削解;

// fetch users with Joe as a first name born in 1970
Query<User> query = userDao.queryBuilder().where(
    Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970)
).build();
List<User> joesOf1970 = query.list();
 
// using the same Query object, we can change the parameters
// to search for Marias born in 1977 later:
query.setParameter(0, "Maria");
query.setParameter(1, 1977);
List<User> mariasOf1977 = query.list();
關(guān)聯(lián)查詢 joinI();
@Entity
public class City {

    @Id
    private Long  id;

    private  String name;

    private  int   population;

    private  Long  countryId;
}
@Entity
public class Country {
    @Id
    private Long  id;

    private  String  name;
}

city 表示持有country 表的id

  QueryBuilder<Country> qb=EntityManager.getInstance().getCountryDao().queryBuilder();
              Join cities= qb.join(City.class,CityDao.Properties.CountryId)
                      .where(CityDao.Properties.Population.gt(1000));
               List<Country> countries =qb.list();

就是 join on 只不過這里它替你寫了 on 的部分,應(yīng)該只是 id 才可以沟娱。

多線程查詢

多條線程執(zhí)行查詢語句時需要調(diào)用forCurrentThread()方法將query對象與當前線程進行綁定氛驮,如果其他線程修改該Query對象,greenDao將會拋出一個異常;forCurrentThread()方法通過將Query創(chuàng)建時的時間作為 query標識;
先看一段代碼

 final   Query<Country> query =EntityManager.getInstance().getCountryDao().queryBuilder().build();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        List<Country> countries =query.list();
                        for (Country c:countries){
                            Log.e("返回",c.getName()+Thread.currentThread().getName());
                        }
                    }
                }).start();

執(zhí)行后會報錯济似,當前的query 已經(jīng)綁定到主線程矫废,這時候在子線程中調(diào)用query 會報錯

08-08 15:56:44.040 4587-4614/com.green.dao E/AndroidRuntime: FATAL EXCEPTION: Thread-314
    Process: com.green.dao, PID: 4587
    org.greenrobot.greendao.DaoException: Method may be called only in owner thread, use forCurrentThread to get an instance for this thread
        at org.greenrobot.greendao.query.AbstractQuery.checkThread(AbstractQuery.java:99)
        at org.greenrobot.greendao.query.Query.list(Query.java:87)
        at com.green.dao.MainActivity$1.run(MainActivity.java:98)
        at java.lang.Thread.run(Thread.java:818)
    

這個錯誤是在哪里拋出的呢?看下list()源碼

 public List<T> list() {
        checkThread();
        Cursor cursor = dao.getDatabase().rawQuery(sql, parameters);
        return daoAccess.loadAllAndCloseCursor(cursor);
    }

    protected void checkThread() {
        if (Thread.currentThread() != ownerThread) {
            throw new DaoException(//就是這里拋出了異常
                    "Method may be called only in owner thread, use forCurrentThread to get an instance for this thread");
        }
    }

啥意思碱屁?list()只能在它自己的線程中調(diào)用。 錯誤提示很清晰了蛾找,用 forCurrentThread 給當前線程一個 query

  final   Query<Country> query =EntityManager.getInstance().getCountryDao().queryBuilder().build();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        List<Country> countries =query.forCurrentThread().list();
                        for (Country c:countries){
                            Log.e("返回",c.getName());
                        }
                    }
                }).start();

這樣就ok 了娩脾。大概就是每個線程要綁定自己的query

所以下面這張寫法肯定沒有問題啦

 new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Query<Country> query =EntityManager.getInstance().getCountryDao().queryBuilder().build();
                        List<Country> countries =query.list();
                        for (Country c:countries){
                            Log.e("返回",c.getName());
                        }
                    }
                }).start();
Sql語句查詢

方式1

 Query<City> query =EntityManager.getInstance().getCityDao().queryBuilder().where(new WhereCondition.StringCondition("_ID IN"+"(SELECT _ID FROM CITY WHERE  _ID=1)")).build();
                City city =query.unique();

StringCondition()中的內(nèi)容:_ID 可以換成任何字段,但是需要跟后面的查詢內(nèi)容保持一致打毛, 雖然后面的sql 語句是如果放到數(shù)據(jù)庫里查詢是只能返回id 但是這里不是 而是返回所有值柿赊。注意 IN 還有sql 語句的括號俩功。

方式2:

Query<City> query =EntityManager.getInstance().getCityDao().queryRawCreate("where _ID=?","1");
                City city=query.unique();
                    Log.e("返回值",city.getPopulation()+"~~~"+city.getName()+"~~~"+city.getId());

方式3

  List<City> citiess=EntityManager.getInstance().getCityDao().queryRaw("where _ID=?","1");
                for (City city:citiess){
                    Log.e("返回值",city.getPopulation()+"~~~"+city.getName()+"~~~"+city.getId());
                }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碰声,隨后出現(xiàn)的幾起案子诡蜓,更是在濱河造成了極大的恐慌,老刑警劉巖胰挑,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔓罚,死亡現(xiàn)場離奇詭異,居然都是意外死亡瞻颂,警方通過查閱死者的電腦和手機豺谈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贡这,“玉大人茬末,你說我怎么就攤上這事「墙茫” “怎么了丽惭?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辈双。 經(jīng)常有香客問我责掏,道長,這世上最難降的妖魔是什么辐马? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任拷橘,我火速辦了婚禮,結(jié)果婚禮上喜爷,老公的妹妹穿的比我還像新娘冗疮。我一直安慰自己,他們只是感情好檩帐,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布术幔。 她就那樣靜靜地躺著,像睡著了一般湃密。 火紅的嫁衣襯著肌膚如雪诅挑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天泛源,我揣著相機與錄音拔妥,去河邊找鬼。 笑死达箍,一個胖子當著我的面吹牛没龙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼硬纤,長吁一口氣:“原來是場噩夢啊……” “哼解滓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筝家,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤洼裤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后溪王,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腮鞍,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年在扰,在試婚紗的時候發(fā)現(xiàn)自己被綠了缕减。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡芒珠,死狀恐怖桥狡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情皱卓,我是刑警寧澤裹芝,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站娜汁,受9級特大地震影響嫂易,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掐禁,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一怜械、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧傅事,春花似錦缕允、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至响鹃,卻和暖如春驾霜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背买置。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工粪糙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人忿项。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓蓉冈,卻偏偏與公主長得像脆栋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子洒擦,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359