greenDao使用指南-1

GreenDao

GreenDao是一個高效的數(shù)據(jù)庫訪問ORM框架,節(jié)省了自己編寫SQL的時間追驴,快速的增刪查改等操作。

介紹就不多說疏之,直接介紹重點吧5钛!体捏!首先po一個github的地址:https://github.com/greenrobot/greenDAO

配置GreenDao

// In your root build.gradle file:
buildscript {
    repositories {
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    }
}
 
// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
 
dependencies {
    compile 'org.greenrobot:greendao:3.2.2' // add library
}

注意咯冠摄,一個是添加在工程的build.gradle糯崎,一個是添加到module的build.gradle文件中.

build.gradlel里面對greenDao進(jìn)行配置几缭。配置之后就搭建好了greenDao的環(huán)境,可以自動生成相關(guān)的類沃呢。

然后你需要配置greenDao的數(shù)據(jù)庫版本號以及自動生成的包名的路徑年栓,當(dāng)然路徑可選擇性的配置。

android{
    ...
}

greendao{
    schemaVersion 2 // 數(shù)據(jù)庫版本號
    daoPackage  'com.doris.sample.greendao'//greenDao 自動生成的代碼保存的包名
    targetGenDir   'src/main/java' //自動生成的代碼存儲的路徑薄霜,默認(rèn)是 build/generated/source/greendao.
    generateTests false //true的時候自動生成測試單元
    targetGenDirTests: 測試單元的生成目錄默認(rèn)是 src/androidTest/java
}

接下來你定義自己的entity并且make project就可以開始對數(shù)據(jù)庫進(jìn)行操作啦某抓。

下面對greenDao的相關(guān)知識點進(jìn)行介紹:

注釋

greenDAO 3 用注釋去schemas 和實體類 entities.例子如下:

@Entity(nameInDb = "user_info",indexes = {
                @Index(value = "name DESC", unique = true)
        },)
public class User {
    @Id
    private Long id;
 
    @Property(nameInDb = "USERNAME") @NotNull
    private String name;
 
    @Transient
    private int tempUsageCount; // not persisted
 
   // getters and setters for id and user ...
}

@Entity將一個Java類轉(zhuǎn)變成一個實體類惰瓜。greenDao會根據(jù)這個生成對應(yīng)的代碼否副。PS: 必須是java類,kotlin不支持崎坊。

在Entity中我們可以配置許多信息备禀,比如nameInDb是聲明了該表數(shù)據(jù)庫中的表名。
indexes 用于建立索引奈揍,索引的應(yīng)用場景可用于曲尸,當(dāng)你的表有多個主鍵的時候,來標(biāo)志一條數(shù)據(jù)的唯一性男翰,配合unique另患。
當(dāng)然上面兩個只是我們常用的屬性,還有幾個其他屬性蛾绎,目前我還沒有用到:
schema = "myschema", 當(dāng)你有多個schema昆箕,用這個屬性來告訴數(shù)據(jù)庫當(dāng)前entity屬于哪個schema鸦列。
active = true,用于標(biāo)志某個entity是否是active的鹏倘,active的實體類有刪改的方法敛熬。默認(rèn)是fale, 為true的時候會自動生成下面的代碼在entity里面:

 /**
    * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
    * Entity must attached to an entity context.
    */
   @Generated(hash = 128553479)
   public void delete() {
       if (myDao == null) {
           throw new DaoException("Entity is detached from DAO context");
       }
       myDao.delete(this);
   }

   /**
    * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
    * Entity must attached to an entity context.
    */
   @Generated(hash = 1942392019)
   public void refresh() {
       if (myDao == null) {
           throw new DaoException("Entity is detached from DAO context");
       }
       myDao.refresh(this);
   }

   /**
    * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
    * Entity must attached to an entity context.
    */
   @Generated(hash = 713229351)
   public void update() {
       if (myDao == null) {
           throw new DaoException("Entity is detached from DAO context");
       }
       myDao.update(this);
   }

基本的屬性:

@Id 標(biāo)志主鍵

@Transient 表示不存儲在數(shù)據(jù)庫中

@NotNull 標(biāo)志這個字段不能是null

@Property 如果定義了這個屬性第股,那么nameInDb的值就是該列在數(shù)據(jù)表里面应民,該列的名稱。上面的例子夕吻,username的值存儲在數(shù)據(jù)表里面的USERNAME那一列诲锹。

主鍵的限制

當(dāng)前,entity必須有一個long或者Long的屬性作為主鍵涉馅,但是有時候我們的主鍵不一定是long或者Long型的可能是string呀之類的归园,這個時候我們就可以定義索引屬性并且注明獨一無二。 如下:

@Index(name = "keyword", unique = true)
private String key;

name用于指明這個索引的列名稚矿,unique表示這個指是不可重復(fù)的庸诱。

@Unique 用于標(biāo)志列的值的唯一性。

greenDao盡最大的可能的合理的安排每個屬性的默認(rèn)值晤揣,所以一般不需要去配置每一個選項桥爽。只需要配置你需要的就可以了。

當(dāng)你編寫好的entity之后昧识,只需要點擊Build-> make project就可以自動生成相關(guān)的代碼了钠四。

如果你改變了已經(jīng)存在的entity記得rebuild工程保證舊的entity類被clean掉了。

記住不要隨意修改注明了@Generated的代碼跪楞,這樣會導(dǎo)致報錯缀去,

Error:Execution failed for task ':app:greendao'.
> Constructor (see ExampleEntity:21) has been changed after generation.
Please either mark it with @Keep annotation instead of @Generated to keep it untouched,
or use @Generated (without hash) to allow to replace it.

解決這個的辦法有兩個:

  1. 將@Generated注釋改回去,或者將自動生成的代碼刪掉甸祭,然后他會自動rebuild在下次build工程的時候缕碎。
  2. 將@Generated改成@Keep,這樣greenDao將不會檢查這段代碼池户,但是這樣可能會導(dǎo)致實體和greenDao其他的契合部分咏雌。另外,未來版本的greenDAO可能會在生成的方法中使用不同的代碼煞檩。最好是不要修改這個处嫌,如果實在要修改,建議編寫測試單元斟湃,測試一下確保不會有問題熏迹。

@Keep在新版本里面已經(jīng)被淘汰了,如果當(dāng)gradle檢測到有@Keep會將他替換成@TransientDW怠坛缕!注意啦!@琛赚楚!

實體類建立好了,那么如何操作數(shù)據(jù)庫骗卜,通過什么訪問數(shù)據(jù)庫呢宠页,先來介紹一下greenDao的幾個關(guān)鍵的類。

關(guān)鍵的幾個類

DaoMaster

greenDao的入口寇仓,持有數(shù)據(jù)庫(SQLiteDatabase)對象 并且 管理Schema的DAO類(不是對象)举户。持有靜態(tài)的創(chuàng)建于刪除表的方法。內(nèi)部類OpenHelper以及DevOpenHelper實現(xiàn)了SQLiteOpenHelper遍烦,創(chuàng)建了數(shù)據(jù)庫模式(Schema)俭嘁。進(jìn)行數(shù)據(jù)庫連接。

DaoSession

管理特定模式的所有可用的DAO對象服猪,通過getter方法可以獲取到DAO對象供填。提供了增刪查改實體的方法。

DAOs

全稱Data access Objects罢猪,數(shù)據(jù)訪問對象近她,對于每一個實體類,greenDao生成一個DAO,持有很多持久性的方法坡脐,例如 count泄私, loadAll以及insertInTx。

Entities

持久化對象(與數(shù)據(jù)庫對應(yīng)的實體類)备闲,對應(yīng)數(shù)據(jù)庫里面的一行。

在用數(shù)據(jù)庫之前首先需要初始化數(shù)據(jù)庫捅暴,一般我們在Application里面進(jìn)行數(shù)據(jù)庫的數(shù)據(jù)化恬砂,并且只初始化一次。

// do this once, for example in your Application class
helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
db = helper.getWritableDatabase();
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();

然后要操作對應(yīng)的對象的時候只需要獲取到對應(yīng)的Dao對象即可:

// do this in your activities/fragments to get hold of a DAO
noteDao = daoSession.getNoteDao();

Session

DaoSession是greenDao重要的接口之一蓬痒,提供了基本的實體類操作泻骤,Daos提供了更多的完整的操作。
獲取Session

daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();

請注意梧奢,數(shù)據(jù)庫連接屬于DaoMaster狱掂,因此多個會話引用相同的數(shù)據(jù)庫連接。 因此亲轨,可以很快創(chuàng)建新的會話趋惨。 但是,每個會話都會分配內(nèi)存惦蚊,通常是實體的會話“緩存”器虾。

Identity scope and session “cache”

如果有兩個查詢返回相同的數(shù)據(jù)庫對象讯嫂,那么您使用的Java對象有多少個:一個還是兩個?它完全取決于身份范圍兆沙。

greenDAO中的默認(rèn)值(行為是可配置的)是多個查詢返回對相同Java對象的引用欧芽。例如,從ID為42的USER表中加載一個User對象為這兩個查詢返回相同的Java對象葛圃。

這個副作用是某種實體“緩存”千扔。如果一個實體對象仍然在內(nèi)存中(greenDAO在這里使用弱引用),則該實體不會再構(gòu)造库正。另外昏鹃,greenDAO不執(zhí)行數(shù)據(jù)庫查詢來更新實體值。相反诀诊,對象會從會話緩存中“立即”返回洞渤,這會比一個或兩個數(shù)量級更快。

清除identity scope

清除整個session属瓣,沒有緩存對象返回

daoSession.clear(); 

清除單個Dao的identity scope 载迄,這樣某個dao不會有緩存對象返回

noteDao = daoSession.getNoteDao();
noteDao.detachAll();

Queries

在GreenDao,你可以自己寫原生的查詢語句抡蛙,也可以通過QueryBuilderAPI來查詢护昧。

Query用于查詢的類

  • QueryBuilder

SQL的語法錯誤只有在run time的時候才會提示,但是用greenDaoQueryBuilder可以在編譯的時候就檢測到錯誤粗截。

查詢范例:

List<User> joes = userDao.queryBuilder()
  .where(Properties.FirstName.eq("Joe"))
  .orderAsc(Properties.LastName)
  .list();

用對應(yīng)的Dao對對應(yīng)的表進(jìn)行查詢操作惋耙,調(diào)用qureyBuilder方法,where是查詢條件熊昌,可以有多個查詢條件绽榛,用逗號分隔開來,如下:

List<User> joes = userDao.queryBuilder()
  .where(Properties.FirstName.eq("Joe"), Properties.AGE.eq("10")
  .orderAsc(Properties.LastName)
  .list();

上面語句查詢lastname是joe的并且年齡是10歲的人婿屹。

復(fù)雜的不是and連接的查詢語句可以如下查詢:

多個條件查詢:

QueryBuilder<User> 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<User> youngJoes = qb.list();

上面語句應(yīng)該如下解釋

 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))

即找出first name是joe的然后出生于1970年10以后的灭美。

order

排序,我們可以對查詢的結(jié)果進(jìn)行排序昂利。

orderAsc(依據(jù)的屬性名稱届腐,可以有多個屬性),正序 orderDesc 倒序

// order by last name
queryBuilder.orderAsc(Properties.LastName);
 
// in reverse
queryBuilder.orderDesc(Properties.LastName);
 
// order by last name and year of birth
queryBuilder.orderAsc(Properties.LastName).orderDesc(Properties.YearOfBirth);

greenDAO使用的默認(rèn)排序規(guī)則是COLLATE NOCASE蜂奸,盡管它可以使用stringOrderCollation()進(jìn)行定制犁苏。 有關(guān)影響結(jié)果順序的其他方法,請參見QueryBuilder類文檔扩所。

limit

當(dāng)你根據(jù)條件查詢围详,返回N條數(shù)據(jù)的時候,但是你只想要里面的前十個的時候碌奉,這個時候用limit可以限制獲取 n條數(shù)據(jù)短曾,不用for循環(huán)cursor寒砖。

limit

limit(int)限制查詢返回的條數(shù)。

需求千變?nèi)f化的嫉拐,有時候你需要的不是前面的n條哩都,而是從位置m開始的n條數(shù)據(jù),這個時候就可以用offset 設(shè)置數(shù)據(jù)返回的偏移值婉徘。

offset(int)

設(shè)置返回數(shù)據(jù)的起始偏移值漠嵌,得到offset開始的n條數(shù)據(jù)。必須要結(jié)合limit(int n)來使用

queryBuilder().where(Properties.YearOfBirth.gt(2001)).offset(3).limit(10)

上面例子是取出出生年份大于2001年的第3個開始的十個人盖呼。

查詢條件總結(jié)

  • eq : Properties.YearOfBirth.eq(2001): 等于
  • notEq : 不等于
  • like:模糊查詢 記住模糊查詢儒鹿,string要用夾在%key%中間。
xxDao.queryBuilder().where(Properties.FirstName.like("%doris%")).list();

查詢FristName包含doris的人几晤。

  • BETWEEN ... AND ... ...和...之間约炎。
  • IN(..., ..., ...) 在給出的value的范圍內(nèi)的符合項
  • gt 大于
  • ge 大于等于
  • lt 小于
  • le 小于等于
  • isNull 不是空的

查詢有懶查詢,也叫延遲查詢吧蟹瘾,我覺得圾浅,就會你先執(zhí)行了查詢語句但是呢只有在你用的時候才會加載到內(nèi)存,就類似于懶加載憾朴。

  • list() 不是懶加載狸捕,正常查詢,查詢結(jié)果立馬加載到內(nèi)存众雷。
  • listLazy() 實體按需加載到內(nèi)存中灸拍。 一旦列表中的元素第一次被訪問,它將被加載并緩存以供將來使用砾省。 必須關(guān)閉鸡岗。
  • listLazyUncached() 一個“虛擬”實體列表:對列表元素的任何訪問都會導(dǎo)致從數(shù)據(jù)庫加載其數(shù)據(jù)。 必須關(guān)閉纯蛾。
  • listIterator() 讓我們通過按需加載數(shù)據(jù)(懶惰地)來遍歷結(jié)果纤房。 數(shù)據(jù)沒有被緩存。 必須關(guān)閉翻诉。

greenDao還支持多線程查詢以及重復(fù)使用Query對象,這個我還沒用到捌刮,用到給大家再深入講解一下哈碰煌!

原始查詢

方法1:

Query<User> query = userDao.queryBuilder().where(
  new StringCondition("_ID IN " +
    "(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)")
).build();

方法2:
queryRawqueryRawCreate

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

debug查詢

QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;

設(shè)置這兩個屬性就可以看到log、

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绅作,一起剝皮案震驚了整個濱河市芦圾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俄认,老刑警劉巖个少,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洪乍,死亡現(xiàn)場離奇詭異,居然都是意外死亡夜焦,警方通過查閱死者的電腦和手機壳澳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茫经,“玉大人巷波,你說我怎么就攤上這事⌒渡。” “怎么了抹镊?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長荤傲。 經(jīng)常有香客問我垮耳,道長,這世上最難降的妖魔是什么遂黍? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任终佛,我火速辦了婚禮,結(jié)果婚禮上妓湘,老公的妹妹穿的比我還像新娘查蓉。我一直安慰自己,他們只是感情好榜贴,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布豌研。 她就那樣靜靜地躺著,像睡著了一般唬党。 火紅的嫁衣襯著肌膚如雪鹃共。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天驶拱,我揣著相機與錄音霜浴,去河邊找鬼。 笑死蓝纲,一個胖子當(dāng)著我的面吹牛阴孟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播税迷,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼永丝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了箭养?” 一聲冷哼從身側(cè)響起慕嚷,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后喝检,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗅辣,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年挠说,在試婚紗的時候發(fā)現(xiàn)自己被綠了澡谭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡纺涤,死狀恐怖译暂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撩炊,我是刑警寧澤外永,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站拧咳,受9級特大地震影響伯顶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骆膝,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一祭衩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阅签,春花似錦掐暮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至养交,卻和暖如春精算,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碎连。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工灰羽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鱼辙。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓廉嚼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親倒戏。 傳聞我的和親對象是個殘疾皇子前鹅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容