GreenDao項目實踐

《一》GreenDao簡單介紹:

1.GreenDao是什么?

官網(wǎng)介紹:GreenDao是Android的一個對象關(guān)系映射(ORM)數(shù)據(jù)庫。

【對象關(guān)系映射ORM】: Object Relational Mapping,對象/關(guān)系數(shù)據(jù)庫,是一種將對象層次結(jié)構(gòu)映射成關(guān)系型結(jié)構(gòu)的方法。將面向?qū)ο笳Z言程序中的對象自動持久化到關(guān)系數(shù)據(jù)庫中。本質(zhì)上就是將數(shù)據(jù)從一種形式轉(zhuǎn)換到另外一種形式。簡單的理解,其實就是Java中每個對象,都對應(yīng)數(shù)據(jù)庫表中的一條數(shù)據(jù)。

2.為什么要選擇GreenDao?

GreenDao特點:

  • 性能最大化(Maximum performance)
  • 易于使用的強大API(Easy to use powerful APIs)
  • 最小內(nèi)存消耗(Minimal memory consumption)
  • 一個小于100KB的精簡的庫(Small library size (<100KB))
  • 數(shù)據(jù)庫加密以保證數(shù)據(jù)的高安全性 (Database encryption)·

(以上均來自官網(wǎng)的介紹

《二》如何使用GreenDao?

可以直接參考Demo的實現(xiàn):EasyGreenDao

easygreendao.gif
Demo功能包括:
1、簡單實體bean和集合List的數(shù)據(jù)庫操作。
2、復(fù)雜實體的數(shù)據(jù)庫操作,如何處理自定義類型的實體及屬性轉(zhuǎn)換器的使用。
例如項目中常常會遇到類似下面這種復(fù)雜List的數(shù)據(jù):
image.png

接下來講解一下GreenDao的使用步驟:
(1)build.gradle中添加greendao依賴,配置數(shù)據(jù)庫版本號、自動生成類的存放目錄等。

apply plugin: 'org.greenrobot.greendao'
android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"
    //greendao
    greendao {
        schemaVersion 1  //數(shù)據(jù)庫版本號,數(shù)據(jù)庫升級時使用
        daoPackage 'com.xxxx.xxx.db.gen'  // 為自動生成的類指定目錄
        targetGenDir 'src/main/java'
    }
}
dependencies {
  //greendao
    compile 'org.greenrobot:greendao:3.2.0'
}

(2)項目目錄下的build.gradle添加:

   //greendao
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'

(3)聲明一個數(shù)據(jù)庫對應(yīng)的實體類,以用戶實體為例

@Entity
public class UserBean {
    @Id
    private Long id;
    public String mobile;//手機號
    public String name;//名字
    public String sex;//性別
  }

Rebuild或Make Project,會自動生成UserBean的get/set方法及對應(yīng)的數(shù)據(jù)庫操作類UserBeanDao及DaoMaster、DaoSession。
(4)創(chuàng)建一個數(shù)據(jù)庫操作管理類DbManager,對數(shù)據(jù)庫相關(guān)操作進行統(tǒng)一封裝處理。(此處只粘貼了部分代碼,完整代碼請戳:EasyGreenDao

public class DbManager {
    private final static String DB_NAME = "easydao.db";
    private static DbManager instance;
    private DaoMaster.DevOpenHelper openHelper;
    private DaoMaster writeDM;
    private DaoMaster readDM;
    private DaoSession daoSession;
    /***
     * 獲取 DbManager 單例
     *
     * @return
     */
    public static DbManager getInstance() {
        DbManager dbManager = instance;
        if (dbManager == null) {
            synchronized (DbManager.class) {
                if (dbManager == null) {
                    instance = new DbManager();
                    dbManager = instance;
                }
            }
        }
        return dbManager;
    }
    private DbManager() {
        openHelper = new DaoMaster.DevOpenHelper(MyApplication.getContext(), DB_NAME, null);
        writeDM = new DaoMaster(openHelper.getWritableDb());
        readDM = new DaoMaster(openHelper.getReadableDb());
    }
    /**
     * 獲取 writeable Dao
     *
     * @param entityClass
     * @return
     */
    private AbstractDao getWriteDao(Class<? extends Object> entityClass) {
        daoSession = writeDM.newSession();
        return daoSession.getDao(entityClass);
    }
        /**
     * 插入或更新(數(shù)據(jù)存在則替換,數(shù)據(jù)不存在則插入)
     *
     * @param entityClass
     * @param object
     * @return
     */
    public long insertOrReplace(Class<? extends Object> entityClass, Object object) {
        if (null == object) {
            return -1L;
        }
        return getWriteDao(entityClass).insertOrReplace(object);
    }
}

(5)例如用戶登錄成功后,需要存儲一個當前用戶的信息。

UserBean   userBean = new UserBean(1l, "18510286862", "小小花", "女");
 long insert = DbManager.getInstance(). insertOrReplace(UserBean.class, userBean);

其他增刪改查的操作請看EasyGreenDao,這里就不贅述了。

《三》關(guān)于自動生成的幾個類:

DaoMaster:DaoMaster 負責管理數(shù)據(jù)庫對象(SQLiteDatabase)和 DAO 類(對象),我們可以通過它內(nèi)部類 OpenHelper 和 DevOpenHelper SQLiteOpenHelper 創(chuàng)建不同模式的 SQLite 數(shù)據(jù)庫。
DaoSession:管理所有的Dao對象。提供通用的插入、查詢、更新和刪除實體的持久化方法。
xxxDao:每個被@Entity注解的實體,都有對應(yīng)的xxxDao對象,通過該xxxDao可以對實體進行增刪改查操作。

《四》GreenDao注解的說明:

- @Id :主鍵 long/Long型,可以通過@Id(autoincrement = true)設(shè)置自增長 
- @Property:設(shè)置一個非默認關(guān)系映射所對應(yīng)的列名,默認是的使用字段名 舉例:@Property (nameInDb=”name”) 
- @NotNul:設(shè)置數(shù)據(jù)庫表當前列不能為空 
- @Transient :添加次標記之后不會生成數(shù)據(jù)庫表的列 
1.)索引注解 
- @Index:使用@Index作為一個屬性來創(chuàng)建一個索引,通過name設(shè)置索引別名,也可以通過unique給索引添加約束 
- @Unique:向數(shù)據(jù)庫列添加了一個唯一的約束 
2.)關(guān)系注解 
- @ToOne:定義與另一個實體(一個實體對象)的關(guān)系 
- @ToMany:定義與多個實體對象的關(guān)系

主鍵的聲明只可能是下面幾種情況,否則會出錯。
自增使用的id必須是Long類型,而非long類型。不然不會自增

 @Id(autoincrement = true)
 private Long id;
 @Id
 private Long id;
 @Id
 private long id;

不需要主鍵自增的情況,可以使用String類型。

 @Id
 private String id;
《五》GreenDao采坑——可能遇到的問題及解決方案

(1) App每次升級版本時,如果對@Entity注解的類有過修改,例如某個數(shù)據(jù)庫實體新增了某字段或修改了字段等,記得在build.gradle中更新schemaVersion數(shù)據(jù)庫版本,否則覆蓋安裝后會崩潰。例如在實體BookEntity新增了des字段,則會報如下錯誤:

Caused by: android.database.sqlite.SQLiteException: table BOOK_ENTITY has no column named DES (Sqlite code 1): , while compiling: INSERT OR REPLACE INTO "BOOK_ENTITY" ("_id","DES","NAME_CN","TAGS","AUTHOR") VALUES (?,?,?,?,?), (OS error - 2:No such file or directory)...

(2)GreenDao 存儲數(shù)據(jù)時,實體里面用@Id 的字段,不可以為int類型,否則會報下面的錯誤

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long...

@Id類型為Long類型時:

android.database.sqlite.SQLiteException: no such column: T._id (Sqlite code 1): , while compiling: SELECT T."_id",T."IMG",T."SORT",T."TYPE",T."LINK",T."PARAM",T."ADD_TIME",T."STATUS",T."BANNERS" FROM "SUBJECT_BEAN" T, (OS error - 2:No such file or directory)...

(3)使用insert插入時,第一次插入正常,如果再插入時如果主鍵id值已經(jīng)存在,則會拋出下面異常。所以我們要求在數(shù)據(jù)庫中插入時,某條記錄不存在則插入,存在則更新。即使用 DbManager.getInstance().insertOrReplace();替代DbManager.getInstance().insert()方法。

Caused by: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: USER_BEAN._id (Sqlite code 1555), (OS error - 2:No such file or directory)

(4)GreenDao 存儲嵌套的集合數(shù)據(jù)時奇怪的Bug


image.png

databaseValue==null,但是最后存儲在集合中的size=1,數(shù)據(jù)為null????之前開發(fā)遇到的bug,暫時還未找到出現(xiàn)原因。

本文參考:
GreenDao官網(wǎng)
GreenDao源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容