greenDAO3 入門(配置,基本操作,數(shù)據(jù)庫升級)

Sqlite作為android重要的數(shù)據(jù)存儲(chǔ)庫,原生類SQLiteOpenHelper使用起來繁瑣容易出錯(cuò),本著"偷懶"的目的,來學(xué)習(xí)一下當(dāng)下十分受歡迎的ORM 框架: greenDAO;網(wǎng)上教程不少,但是大都是針對3.0之前的版本,greenDAO2和3的構(gòu)建和生成代碼的方式區(qū)別很大,最終還是通過greenDAO github上的介紹,慢慢摸索,成功的在項(xiàng)目中構(gòu)建了greenDAO,本文章寫于greenDao更新至3.2版本

一、什么是greenDAO?

官方介紹:
greenDAO github
greenDAO 官網(wǎng)
網(wǎng)友的博客:
Android ORM框架 GreenDao3.0的使用

greenDAO3開始使用注解的方式定義實(shí)體類(entity),并且是通過安裝gradle插件來生成代碼。

二、如何使用greenDAO

構(gòu)建之前,不熟悉gradle概念的同學(xué)建議學(xué)習(xí)Gradle for android 系列教程

先來看下greenDAO 官方構(gòu)建介紹:

greenDAO github 構(gòu)建介紹
開始搭建:
  • github中提示添加maven倉庫,但是android studio 項(xiàng)目已經(jīng)默認(rèn)包含了jcenter倉庫,而jcenter倉庫就是maven倉庫的一個(gè)分支,因此我們不要再添加倉庫,直接添加classPath即可
項(xiàng)目下build.gradle
  • 在moudle下的build.gradle文件中 申明插件以及配置greendao(可以不配置)
moudle 下build.gradle腳本中配置
  • 并在dependencies中添加compile
  /* green dao */
  compile 'org.greenrobot:greendao:3.2.0

三、使用greenDAO

  1. 編寫實(shí)體類:User類,使用greendao @Entity注解
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
@Entity
public class User {
    @Id
    private long id;
    private String userName;
    private int age;
    private String gender;
}
  1. 編譯項(xiàng)目,build后greendao插件會(huì)為所有帶有該注解的實(shí)體生成Dao文件,以及DaoManager與DaoSession,默認(rèn)生成目錄為build/generated/source ,如果我們在gradle腳本中配置了,則會(huì)生成在我們的配置目錄
在配置目錄中生成dao文件

不配置,則在默認(rèn)目錄(build/generated/source/greendao)下生成dao文件:

不配置,則在默認(rèn)目錄下生成dao文件

四、greenDAO 注解

1.實(shí)體@Entity注解

schema:告知GreenDao當(dāng)前實(shí)體屬于哪個(gè)schema
active:標(biāo)記一個(gè)實(shí)體處于活動(dòng)狀態(tài),活動(dòng)實(shí)體有更新、刪除和刷新方法
nameInDb:在數(shù)據(jù)中使用的別名,默認(rèn)使用的是實(shí)體的類名
indexes:定義索引,可以跨越多個(gè)列
createInDb:標(biāo)記創(chuàng)建數(shù)據(jù)庫表
2.基礎(chǔ)屬性注解

@Id :主鍵 Long型,可以通過@Id(autoincrement = true)設(shè)置自增長
@Property:設(shè)置一個(gè)非默認(rèn)關(guān)系映射所對應(yīng)的列名,默認(rèn)是的使用字段名 舉例:@Property (nameInDb="name")
@NotNul:設(shè)置數(shù)據(jù)庫表當(dāng)前列不能為空
@Transient :添加次標(biāo)記之后不會(huì)生成數(shù)據(jù)庫表的列
3.索引注解

@Index:使用@Index作為一個(gè)屬性來創(chuàng)建一個(gè)索引,通過name設(shè)置索引別名,也可以通過unique給索引添加約束
@Unique:向數(shù)據(jù)庫列添加了一個(gè)唯一的約束
4.關(guān)系注解

@ToOne:定義與另一個(gè)實(shí)體(一個(gè)實(shí)體對象)的關(guān)系
@ToMany:定義與多個(gè)實(shí)體對象的關(guān)系

五、使用greenDAO 進(jìn)行數(shù)據(jù)操作(詳情可查閱博友的文章

  • 使用單例模式構(gòu)建一個(gè)工具類來獲取daoSession等對象
public class GreenDaoHelper {

    private static DaoMaster.DevOpenHelper devOpenHelper;
    private static SQLiteDatabase database;
    private static DaoMaster daoMaster;
    private static DaoSession daoSession;

    /**
     * 初始化greenDao
     * 建議放在Application 中進(jìn)行
     */

    public static void initDatabase(){
        // 通過 DaoMaster 的內(nèi)部類 DevOpenHelper,你可以得到一個(gè)便利的 SQLiteOpenHelper 對象。
        // 可能你已經(jīng)注意到了,你并不需要去編寫「CREATE TABLE」這樣的 SQL 語句,因?yàn)?greenDAO 已經(jīng)幫你做了。
        // 注意:默認(rèn)的 DaoMaster.DevOpenHelper 會(huì)在數(shù)據(jù)庫升級時(shí),刪除所有的表,意味著這將導(dǎo)致數(shù)據(jù)的丟失。
        // 所以,在正式的項(xiàng)目中,你還應(yīng)該做一層封裝,來實(shí)現(xiàn)數(shù)據(jù)庫的安全升級。
        devOpenHelper = new DaoMaster.DevOpenHelper(AppContext.getInstance(),"cache-db",null);//數(shù)據(jù)庫名
        database = devOpenHelper.getWritableDatabase();
        // 注意:該數(shù)據(jù)庫連接屬于 DaoMaster,所以多個(gè) Session 指的是相同的數(shù)據(jù)庫連接。
        daoMaster = new DaoMaster(database);
        daoSession = daoMaster.newSession();
    }

    public static DaoSession getDaoSession() {
        return daoSession;
    }
    public static SQLiteDatabase getDb() {
        return database;
    }
}

數(shù)據(jù)庫的增刪改查我們都將通過Dao來操作

  • 增加數(shù)據(jù)(直接inser一個(gè)對象即可,十分簡便)
 private UserDao mUserDao = GreenDaoHelper.getDaoSession().getUserDao();

    public void insertData(){
        //數(shù)據(jù)庫的增刪改查我們都將通過UserDao來進(jìn)行,插入操作如下:
        mUserDao.insert(new User(null,"david",23,"male"));//id傳null 即自增。==> 這里是Long類型而不是long
    }

小手一抖,一口氣插了6條數(shù)據(jù):

小手一抖,一口氣插了6條數(shù)據(jù)
  • 刪除數(shù)據(jù)(刪除數(shù)據(jù)和修改數(shù)據(jù)的思路一樣,都是要先查找到數(shù)據(jù)),操作很簡單,效果就不一一截圖了
//查詢id等于3的所有行并刪除
User user = mUserDao.queryBuilder().where(UserDao.Properties.Id.eq(3)).build().unique();
if (user == null)   ToastUtils.show(getView(), "用戶不存在!");
else   mUserDao.deleteByKey(user.getId());
//查詢id小于5的集合并刪除
List<User> userList = (List<User>) mUserDao.queryBuilder().where(UserDao.Properties.Id.le(5)).build().list();
for (User user : userList) {
    mUserDao.delete(user);
}
//刪除所有數(shù)據(jù)
mUserDao.deleteAll();

  • 修改數(shù)據(jù)
//修改id為2的行 
User user = new User((long) 2, "Nancy", 23, "female");
mUserDao.update(user);
//查詢id>= 3 且like ("%david%")
User user = mUserDao.queryBuilder()
                .where(UserDao.Properties.Id.ge(3), UserDao.Properties.UserName.like("%david%")).build().unique();
if (user == null) {
    ToastUtils.show(getView(), "用戶不存在!");
} else {
    user.setUserName("王五");
    mUserDao.update(user);
}

  • 查詢數(shù)據(jù)
//查出所有數(shù)據(jù)
List<User> users = mUserDao.loadAll();    

//查詢id為1~4之間的數(shù),查出前2個(gè)
List<User> users = mUserDao.queryBuilder()
                .where(UserDao.Properties.Id.between(1, 4)).limit(2).build().list();

六、數(shù)據(jù)庫升級

數(shù)據(jù)庫升級的意義:

如果我們再項(xiàng)目中使用了數(shù)據(jù)庫。而數(shù)據(jù)庫的結(jié)構(gòu)在第一版的時(shí)候定下來,之后發(fā)布功能更新,或增加業(yè)務(wù)邏輯,原來的數(shù)據(jù)庫結(jié)構(gòu)可能就不適用了。而如果數(shù)據(jù)庫的結(jié)構(gòu)與之前版本的結(jié)構(gòu)不同,新版本的應(yīng)用讀取舊數(shù)據(jù)庫肯定會(huì)出問題。解決辦法只有兩種:
1.讓用戶卸載老版本再安裝新的程序;
2.軟件自行更新數(shù)據(jù)庫結(jié)構(gòu)。
第一種辦法很明顯不具備可操作性,而且用戶一旦卸載軟件,數(shù)據(jù)就丟失了,這是不能容忍的事情。因此,作為開發(fā)者必須妥善處理數(shù)據(jù)庫的升級問題。

  • 修改gradle文件

首先在module的gradle文件中修改版本號:

//改為最新的版本號  
schemaVersion 2  

如果只是做了上面的步驟則會(huì)默認(rèn)清除所有數(shù)據(jù),一看源碼便知,當(dāng)檢測到version變化的時(shí)候便執(zhí)行dropAllTables()操作,再重新建庫

    /** WARNING: Drops all table on Upgrade! Use only during development. */
    public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name) {
            super(context, name);
        }

        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }

數(shù)據(jù)遷移的核心思想:
1 把舊表改為臨時(shí)表
2 建立新表
3 臨時(shí)表數(shù)據(jù)寫入新表,刪除臨時(shí)表

站在巨人的肩膀上,這里直接使用了開源的庫,配合greenDAO來做數(shù)據(jù)遷移,親測穩(wěn)定:
GreenDaoUpgradeHelper

schemaVersion 版本加1,User類新增屬性:major

不做遷移處理前,重新安裝后數(shù)據(jù)庫已經(jīng)被重置,數(shù)據(jù)為空。遷移配置后,舊表數(shù)據(jù)已經(jīng)被存到新表中,major字段為null;


數(shù)據(jù)遷移成功

使用方式該git上面介紹的很詳細(xì)了,不再贅述。
感謝前輩們的無私分享。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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