GreenDao入門

1. 什麼是greenDao

弄明白greenDao以前咱們應該先了解什麼是ORM(Object Relation Mapping 即 對象關係映射),說白了就是將面向對象編程語言裏的對象與數據庫關聯起來的一種技術,而greenDao就是實現這種技術之一,因此說greenDao其實就是一種將java object 與SQLite Database關聯起來的橋樑,它們之間的關係 以下圖所示;java

2. 爲何要使用greenDao

greenDao能夠說是當今最流行,最高效並且還在迭代的關係型數據庫。並且greenDao3.0還支持RxJava操做,greenDao如此受歡迎離不開如下幾點:android

  • 存取速度快數據庫

    每秒中能夠操做數千個實體 下圖是幾種常見關係型數據庫性能比較;

  • 支持數據庫加密編程

    支持android原生的數據庫SQLite,也支持SQLCipher(在SQLite基礎上加密型數據庫)。
  • 輕量級segmentfault

    greenDao的代碼庫僅僅100k大小
  • 激活實體緩存

    處於激活狀態下的實體能夠有更多操做方法
  • 支持緩存session

    可以將使用的過的實體存在緩存中,下次使用時能夠直接從緩存中取,這樣可使性能提升N個數量級
  • 代碼自動生成多線程

    greenDao 會根據modle類自動生成實體類(entities)和Dao對象,而且Dao對象是根據entities類量身定作的而且一 一對應。

3. 怎樣使用greenDao

3.1 入門

3.1.1 配置GreenDaoapp

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
     classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'//greenDao生產代碼插件
    }
apply plugin: 'org.greenrobot.greendao'//greendao插件
dependencies {
      compile 'org.greenrobot:greendao:3.2.0'

配置數據庫信息maven

greendao {
        //數據庫schema版本,也能夠理解爲數據庫版本號
        schemaVersion 2
        //設置DaoMaster 、DaoSession、Dao包名
        daoPackage 'com.qhn.bhne.footprinting.db'
        //設置DaoMaster 、DaoSession、Dao目錄
        targetGenDir 'src/main/java'
        //設置生成單元測試目錄
//    targetGenDirTest
        //設置自動生成單元測試用例
//    generateTests
    }

到這裏數據庫基本配置已經完成,接下來讓咱們一塊兒來了解下greenDao的核心類該怎樣使用吧。
3.1.2 核心類介紹

  • DaoMaster:

    • 是GreenDao的入口也是greenDao頂級對象,對於一個指定的表單持有數據庫對象(SQLite數據庫)而且可以管理DAO類
    • 可以建立表和刪除表
    • 其內部類OpenHelper 與DevOpenHelper是建立SQlite數據庫的SQLiteOpenHelper的具體實現
  • DaoSession:

    • 對於一個指定的表單能夠管理全部的Dao 對象。
    • 也可以對實體類執行 insert ,load,update,refresh.delete操做。
    • DaoSession也能跟蹤 identity scope:即session查詢後的實體會存在緩存中,並給該實體生成一個flag來追蹤該實體,下次再次查詢時會直接從緩存中取出來而不是從數據庫中取出來
  • DAOS

    • 可以持久訪問和查詢實體類
    • 比起DaoSession有更多的持久化方法 count, loadAll,insertInt等等;
  • Entities - 自動生成的代碼,通常狀況下與javaBean對象的屬性一一對應。

3.1.3 構建Model類

Molde類須要用java類來定義而且能夠經過GreenDao中的註釋來代表Model中的每一個屬性在數據庫的中該如何定義;定義model類後點擊Make project選項GreenDao就會自動生成DaoMaster,DaoSession,和DAOS類,生成的代碼將會保存在預先在budle gradle中設置的位置

  • 實體和註釋

    GreenDao 經過註釋來定義表單與實體
@Entity
public class User { 
        @Id 
        private Long id;  private String name; 
        @Transient 
        private int tempUsageCount; // 沒有存入數據庫中
 }

@Entity

  • 告訴GreenDao 該Bean類須要持久化。只有使用@Entity註釋的Bean類才能被dao類操做;
  • @Entity能夠在不使用參數下使用,可是也能夠給Entity配置參數,其參數以下
//若是該實體屬於多個表單,可使用該參數; 
schema = "myschema",  
// 該實體屬於激活狀態,激活狀態的實體有更新,刪除,刷新方法; 
active = true,  
// 給這個表指定一個名字,默認狀況下是名字是類名 
nameInDb = "AWESOME_USERS",
 // 能夠給多個屬性定義索引和其餘屬性.
 indexes = { @Index(value = "name DESC", unique = true) },  
//是否使用GreenDao建立該表.
 createInDb = false,   
// 是否全部的屬性構造器都應該被生成,無參構造器老是被要求
 generateConstructors = true,  
// 若是該類中沒有set get方法是否自動生成 
generateGettersSetters = true
  • 基本註釋屬性

    • @ID 通常會選擇long/Long屬性做爲Entity ID(即數據庫中的主鍵)autoincrement=true表示主鍵會自增若是false就會使用舊值
    • @Property 能夠自定義一個該屬性在數據庫中的名稱,默認狀況下數據庫中該屬性名稱是Bean對象中的 屬性名可是不是以駝峯式而是以大寫與下劃線組合形式來命名的好比:customName將命名爲 CUSTOM_NAME;注意:外鍵不能使用該屬性;
    • @NotNull 確保屬性值不會爲null值;
    • @Transient 使用該註釋的屬性不會被存入數據庫中;
    • @Unique 將屬性變成惟一約束屬性;也就是說在數據庫中該值必須惟一
    • @Generated 提示開發者該屬性不能被修改;而且實體類的方法,屬性,構造器一旦被@Generated註釋就不能被再次修改,不然或報錯

      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.
這是由於在經過javabean對象自動生成entities類時,greenDao會增長實體類代碼,@Generated註釋部分與GreenDao增長的代碼相關,胡亂修改@Generated代碼,就會致使entities部分屬性與javabean不匹配致使報錯;有倆種方法能夠避免這種錯誤

    *   還原**@Generated** 改動的部分,固然你也能夠徹底刪除@Generated 註釋的部分下一次 app build時將會自動生成;

    *   使用**@Keep** 代替**@Generated** 這將告訴greenDao 不會使用該屬性註釋的代碼,可是這種改變可能會破壞entities類和greenDAO的其餘部分的鏈接;注意:默認狀況下 greenDao會使用合理的默認值去設置實體類,所以開發者不須要爲每一個屬性都添加註釋
@Entity
public class User { 
      @Id(autoincrement = true)
       private Long id;  
      @Property(nameInDb = "USERNAME") 
       private String name;  
      @NotNull 
      private int repos;  
      @Transient 
      private int tempUsageCount; 
 ...}
    • *
  • 主鍵限制

    每一個實體類都應該有一個long或者LONG型屬性做爲主鍵;若是你不想用long或者LONG型做爲主鍵,你可使用一個惟一索引(使用@Index(unique = true)註釋使普通屬性改變成惟一索引屬性)屬性做爲關鍵屬性。
@Id
private Long id; 
@Index(unique = true)
private String key;
  • 索引屬性
    使用@Index 能夠將一個屬性變爲數據庫索引;其有倆個參數

    • name :不使用默認名稱,自定義索引名稱
    • unique : 給索引增長一個惟一約束,迫使該值惟一
@Entity
public class User { 
@Id 
private Long id;
 @Index(unique = true)
 private String name;
}
  • 核心代碼初始化
    建立數據庫過程

    // 下面代碼僅僅須要執行一次,通常會放在application
    helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
    db = helper.getWritableDatabase();
    daoMaster = new DaoMaster(db);
    daoSession = daoMaster.newSession();
    // 在activity或者fragment中獲取Dao對象
    noteDao = daoSession.getNoteDao()
完成以上全部工做之後,咱們的數據庫就已經自動生成了,接下來就能夠對數據庫進行操做了;
  • 增刪改查
    greenDao的增,刪 ,改操做比較簡單分別調用insert(),delete(),update()方法便可,save()方法比較特殊既能執行插入操做也能執行修改操做這個具體的能夠查看greenDaoAPI

    • Query
      與原生SQLitedatabases的查詢操做相比,greenDao Query簡直不能再簡單;greenDao 使用QueryBuilder構建查詢語句也支持原生的SQL查詢語句

      • 簡單的查詢語句 在用戶表中查詢叫姓「Joe」的全部的用戶:

        List joes = userDao.queryBuilder() 
        .where(Properties.FirstName.eq("Joe")) 
        .orderAsc(Properties.LastName) .list();
*   嵌套挑去查詢語句:查詢一個出生在1970年10月或者之後的"joe"用戶
QueryBuilder qb = userDao.queryBuilder();
qb.where(Properties.FirstName.eq("Joe"),//第一個約束條件姓喬
qb.or(Properties.YearOfBirth.gt(1970),//或者出生日期大於1970年
qb.and(Properties.YearOfBirth.eq(1970), 
Properties.MonthOfBirth.ge(10))//而且在1970年出生 可是月份大於
10月的));
List youngJoes = qb.list();
greenDao除了eq()操做以外還有不少其餘方法大大方便了咱們平常查詢操做好比:
    *   eq():==
    *   noteq():!=
    *   gt(): >
    *   lt():<
    *   ge:>=
    *   le:<=
    *   like():包含
    *   between:倆者之間
    *   in:在某個值內
    *   notIn:不在某個值內
  • 分頁查詢

    • limit(int): 限制查詢的數量;
    • offset(int): 每次返回的數量; offset不能單獨使用;
  • 查詢與LazyList類

    • Query : Query類表示一個查詢可以執行不少次;而當經過QueryBuilder的任何查詢方法(eg:list())來獲取查詢結果時,querybuilder都會 在其內部建立Query來執行查詢語句的;若是執行屢次查詢應該使用Query對象; 若是隻想獲取一個結果時可使用Query(or QueryBuilder)中的unique()方法;
    • LazyList : 能夠經過如下方法獲取查詢結果集合;

      • list() 緩存查詢結果;list()類型通常爲ArrayList
      • listLazy() 懶查詢,只有當調用list()中的實體對象時纔會執行查詢操做而且只緩存第一次被查詢的結果,須要關閉
      • listlazyUncached() 懶查詢,只有當調用list()中的實體對象時纔會執行查詢操做而且不緩存;
      • listIterator() 對查詢結果進行遍歷,不緩存,須要關閉;

後面三個方法是LazyList類中的方法,LazyList爲了執行不一樣的緩存策略其內部持有數據庫的cursor對象;通常狀況下這三個方法執行完畢後會自動關閉cursor;可是防止在尚未執行完查詢結果時,對象被終結cursor仍是沒法被關閉的狀況發生,須要手動關閉close();

  • 屢次執行查詢語句

    Query對象一旦生成就能屢次被使用,你也能夠爲下一次查詢增長查詢條件
// fetch users with Joe as a first name born in 1970Query 
query = userDao.queryBuilder().where( 
Properties.FirstName.eq("Joe"), 
Properties.YearOfBirth.eq(1970)).build();List 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 mariasOf1977 = query.list();
  • 在多線程執行查詢
    若是有多條線程執行查詢語句時須要調用forCurrentThread()方法將query對象與當前線程進行綁定,若是其餘線程修改該Query對象,greenDao將會拋出一個異常;forCurrentThread()方法經過將Query建立時的時間做爲 query標識;
  • 使用SQL查詢
    若是QueryBuilder不能知足需求可使用如下倆種方法來實現你的需求;

    • 首選方法用SQL語句:

      Query query = userDao.queryBuilder().where( new 
      StringCondition("_ID IN " + "(SELECT USER_ID FROM 
      USER_MESSAGE WHERE READ_FLAG = 0)")).build();
*   備選方法 :
    使用queryRaw 或者queryRawCreate:
Query query = userDao.queryRawCreate( ", GROUP G WHERE 
G.NAME=? AND T.GROUP_ID=G._ID", "admin");

好了這一期的GreenDao的介紹到這裏就結束了,本期主要講解了greenDao的基本概念與基本操做,下一期(史上最高效的ORM方案——GreenDao3.0高級用法)我會介紹GreenDao的高級操做:session緩存多表查詢多表關聯自定義參數類型。若是你以爲本篇本章有什麼不足的地方歡迎在評論區留言;

相關文章
相關標籤/搜索