Skip to main content
Select a menu in the customizer

GreenDao 3 Introduction

greendao-vs-ormlite-vs-activeandroid

首先先來一張 GreenDao 3 官方的自吹自擂,雖然看起來跟 GreenDao 2 差不多,就是尬爆其他目前所有 ORM Lib 的效能,會這樣說是因為之前就是用 GreenDao 2 作為主要開發 DB 框架,當時就看到同一張圖表。詳情可以看這一篇 『Android ORM Library- Green DAO(一) introduction』。基於以上理由,這次更新,自然就開開心心得來試試看。至於好處壞處使用原因情境,全部跟前一篇一模一樣,不再贅述。

雖然 Greendao 2 時用的就不是很深入,但是現在一比較發現,這次改進最大的就是建制基本 DAO 的方法,活用了 android studio 中的 gradle plugin。會這樣說就是以前的方法實在不好上手,必需要先在 project 外建置一個 java file,對,就是有一個 public static main 的那種程式,然後把欄位寫進去,在搭配 Gradle 的插件『greendao generator』才能自動生成 DaoMaster , DaoSession , xxxDao , xxxEnity 等 Class,這件事大大地讓我不想要隨便去改動 db ,因為實在麻煩,而且那個 java file 根本不會在用到,可說是廢 code.

而現在則是大大改進那一堆我都不知道上面再說啥的部份,因此接下來慢慢一步一步得來解說到底變成怎麼樣了

step 1. 一樣先在 build.gradle 裡加入

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'
    }
}

apply plugin: 'org.greenrobot.greendao'

dependencies {
    compile 'org.greenrobot:greendao:3.2.0'
}

step 2 . 然後厲害的部份就來啦,可以開始創 dao

這邊以官方範例 note 物件來寫,以 id , text , date 作為欄位名稱。只要在要使用的專案中多加個 class , 像是 Note.java ,並在 class 上加入 annotation Entity 就可以搞定, 接下來根據需求設定其他 annotation 像是 Id , NotNull  , Unique 之類的。

@Entity
public class Note {
 
    @Id
    private Long id;
 
    @NotNull
    private String text;
    private Date date;
}

補充:

  • The @Id annotation selects a long/ Long property as the entity ID. In database terms, it’s the primary key. The parameter autoincrement is a flag to make the ID value ever increasing (not reusing old values).
  • @Property lets you define a non-default column name, which the property is mapped to. If absent, greenDAO will use the field name in a SQL-ish fashion (upper case, underscores instead of camel case, for example customName will become CUSTOM_NAME). Note: you currently can only use inline constants to specify a column name.
  • @NotNull makes the property a “NOT NULL” column on the database side. Usually it makes sense to mark primitive types (long, int, short, byte) with @NotNull, while having nullable values with wrapper classes (Long, Integer, Short, Byte).
  • @Transient marks properties to be excluded from persistence. Use those for temporary states, etc. Alternatively, you can also use the transient keyword from Java.

step3 . Note.java 寫好後直接按 project make ,然後喝個咖啡, Note.java 就會搖身一遍成…..

『一個加強版的 Note.java』

多了一堆有的沒有的 setter , getter ,沒錯這樣就完成啦,一個全新的 entity,另外啥小 DaoMaster , DaoSession , xxxDao 也都跟者一起跑出來。預設 package 會是 note.java 的 package 。gen dir 是 src/java/main

@Entity(indexes = {
    @Index(value = "text, date DESC", unique = true)
})
public class Note {

    @Id
    private Long id;

    @NotNull
    private String text;
    private String comment;
    private java.util.Date date;

    @Convert(converter = NoteTypeConverter.class, columnType = String.class)
    private NoteType type;

    @Generated(hash = 1272611929)
    public Note() {
    }

    public Note(Long id) {
        this.id = id;
    }

    @Generated(hash = 1686394253)
    public Note(Long id, @NotNull String text, String comment, java.util.Date date, NoteType type) {
        this.id = id;
        this.text = text;
        this.comment = comment;
        this.date = date;
        this.type = type;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @NotNull
    public String getText() {
        return text;
    }

    /** Not-null value; ensure this value is available before it is saved to the database. */
    public void setText(@NotNull String text) {
        this.text = text;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public java.util.Date getDate() {
        return date;
    }

    public void setDate(java.util.Date date) {
        this.date = date;
    }

    public NoteType getType() {
        return type;
    }

    public void setType(NoteType type) {
        this.type = type;
    }

}

如果不喜歡這個生成的位址。就在 gradle 加入設定

greendao {
    schemaVersion 2
    daoPackage  'com.android.heaton.database'
    targetGenDir 'src/main/java'
}

補充:

  • schemaVersion: The current version of the database schema. This is used by the *OpenHelpers classes to migrate between schema versions. If you change your entity/database schema, this value has to be increased. Defaults to 1.版本號
  • daoPackage: The package name for generated DAOs, DaoMaster, and DaoSession. Defaults to the package name of your source entities. 生成 Package PATH
  • targetGenDir: The location where generated sources should be stored at. Defaults to the generated source folder inside the build directory ( build/generated/source/greendao).
  • generateTests: Set to true to automatically generate unit tests.
  • targetGenDirTests: The base directory where generated unit tests should be stored at. Defaults tosrc/androidTest/java.

step 4.  到這階段就是一般 CRUD

Query:通常都會使用 QueryBuilder 作為query的主要輔助工具,where , or 之類的 sql statement 用物件的方式表現出來

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();
  • list() All entities are loaded into memory. The result is typically an ArrayList with no magic involved. Easiest to use. 最常見的一班用法,返回 ArrayList
  • listLazy() Entities are loaded into memory on-demand. Once an element in the list is accessed for the first time, it is loaded and cached for future use. Must be closed. 分階段讀取,當真的需要時,才會讀取。
  • listLazyUncached() A “virtual” list of entities: any access to a list element results in loading its data from the database. Must be closed. 不經過 memory cache,直接去 db access 
  • listIterator() Let’s you iterate through results by loading the data on-demand (lazily). Data is not cached. Must be closed. 基本上同第一個

Insert:

// Insert one object
NoteDataDao.insert(new NoteData());
// Insert and update object
NoteDataDao.insertOrReplace(new NoteData());
// block insert objects
NoteDataDao.insertInTx(List list);

Update:

NoteDataDao.update(new NoteData());
NoteDataDao.updateKeyAfterInsert(new NoteData() , 2);
NoteDataDao.updateInTx(list);

 

Delete

NoteDataDao.deleteAll();
NoteDataDao.deleteByKey(list);
NoteDataDao.deleteInTx(list);
//  最常見的還是給予條件式然後刪除符合條件的物件,這就一樣需要 query builder 
//  去 build 出 delete sql statement  
NoteDataDao.queryBuilder(XXX condition ).buildDelete().executeDeleteWithoutDetachingEntities();

ps. Greendao 3 依然沒有可以設定 entity 欄位初始值功能,詳情依樣可以看Android ORM Library – Green DAO(二)Question: Why can’t set default value for entities

因為之前已經寫過一篇很詳細的,這次就不詳述,只談差異部分,感謝收看

 

reference:

http://greenrobot.org/greendao/documentation/
Android数据存储之GreenDao 3.0 详解