Android框架之路——GreenDao3.2.2的使用

CSDN同步更新:http://blog.csdn.net/bskfnvjtlyzmv867/article/details/71250101

一诈火、簡介

GreenDAO是一個開源的安卓ORM框架料皇,能夠使SQLite數(shù)據(jù)庫的開發(fā)再次變得有趣。它減輕開發(fā)人員處理低級數(shù)據(jù)庫需求碳想,同時節(jié)省開發(fā)時間凤薛。 SQLite是一個令人敬畏的內(nèi)嵌的關(guān)系數(shù)據(jù)庫,編寫SQL和解析查詢結(jié)果是相當乏味和耗時的任務砸讳。通過將Java對象映射到數(shù)據(jù)庫表(稱為ORM优构,“對象/關(guān)系映射”)诵叁,GreenDAO可以將它們從這些映射中釋放出來,這樣钦椭,您可以使用簡單的面向?qū)ο蟮腁PI來存儲拧额,更新,刪除和查詢數(shù)據(jù)庫彪腔。

簡單的講侥锦,GreenDAO 是一個將對象映射到 SQLite 數(shù)據(jù)庫中的輕量且快速的 ORM 解決方案。

<p>

</p>

二德挣、ORM概念

對象-關(guān)系映射(OBJECT/RELATIONALMAPPING恭垦,簡稱ORM),是隨著面向?qū)ο蟮能浖_發(fā)方法發(fā)展而產(chǎn)生的格嗅。用來把對象模型表示的對象映射到基于SQL的關(guān)系模型數(shù)據(jù)庫結(jié)構(gòu)中去番挺。這樣,我們在具體的操作實體對象的時候屯掖,就不需要再去和復雜的 SQL 語句打交道玄柏,只需簡單的操作實體對象的屬性和方法。ORM 技術(shù)是在對象和關(guān)系之間提供了一條橋梁贴铜,前臺的對象型數(shù)據(jù)和數(shù)據(jù)庫中的關(guān)系型的數(shù)據(jù)通過這個橋梁來相互轉(zhuǎn)化粪摘。

簡單的講瀑晒,就是JavaBean和我們的數(shù)據(jù)庫進行一個關(guān)系映射,一個實例對象對應數(shù)據(jù)庫的一條記錄徘意,每個對象的屬性則對應著數(shù)據(jù)庫表的字段苔悦。

三、添加依賴

// 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
}

四映砖、解鎖技能

  1. GreenDao 3.0采用注解的方式來定義實體類间坐,通過gradle插件生成相應的代碼灾挨。您可以使用greenDAO Gradle插件邑退,無需任何其他配置,但至少要設置schema的版本等;

     // In the build.gradle file of your app project:
     android {
     ...
     }
      
     greendao {
         schemaVersion 1
         daoPackage 'com.ping.greendao.gen'
         targetGenDir 'src/main/java'
     }
    

此外,greendao配置元素支持多種配置選項:
- schemaVersion:指定數(shù)據(jù)庫schema版本號劳澄,遷移等操作會用到地技;
- daoPackage:通過gradle插件生成的數(shù)據(jù)庫相關(guān)文件的包名,默認為你的entity所在的包名秒拔;
- targetGenDir:自定義生成數(shù)據(jù)庫文件的目錄莫矗,可以將生成的文件放到我們的java目錄中,而不是build中砂缩,這樣就不用額外的設置資源目錄了作谚。

  1. 通過GreenDao3注解的語法來定義我們的一個數(shù)據(jù)庫實體類及其數(shù)據(jù)庫操作方法;
    • 我們先生成一個實體類——Meizi庵芭,包含id妹懒、來源、和圖片url地址双吆;

        public class Meizi {
        
            private String _id;
            private String source;
            private String url;
        }
      
    • 通過添加注解為我們的Meizi實體類生成對應的數(shù)據(jù)庫操作方法眨唬;

        @Entity
        public class Meizi {
        
            @Id(autoincrement = true)
            private Long _id;
            private String source;
            @NotNull
            private String url;
        }
      

這里的幾個注解含義:
- @Entity:將我們的java普通類變?yōu)橐粋€能夠被greenDAO識別的數(shù)據(jù)庫類型的實體類;
- @nameInDb:在數(shù)據(jù)庫中的名字,如不寫則為實體中類名好乐;
- @Id:選擇一個long / Long屬性作為實體ID匾竿。 在數(shù)據(jù)庫方面,它是主鍵蔚万。 參數(shù)autoincrement是設置ID值自增岭妖;
- @NotNull:使該屬性在數(shù)據(jù)庫端成為“NOT NULL”列。 通常使用@NotNull標記原始類型(long反璃,int区转,short,byte)是有意義的版扩;
- @Transient:表明這個字段不會被寫入數(shù)據(jù)庫废离,只是作為一個普通的java類字段,用來臨時存儲數(shù)據(jù)的礁芦,不會被持久化蜻韭。

- 通過點擊AndroidStudio中的MakeProject悼尾,便發(fā)現(xiàn)GreenDao為我們的Meizi實體類生成了對應的Getter、Setter方法以及倆個構(gòu)造函數(shù)肖方,同時在我們配置的com.ping.greendao.gen包下生成了三個對應類文件DaoMaster闺魏、DaoSession和MeiziDao,之后所有相關(guān)的數(shù)據(jù)庫操作都依靠這三個文件了俯画;

        @Entity
        public class Meizi {
        
            @Id(autoincrement = true)
            private Long _id;
            private String source;
            @NotNull
            private String url;
            @Generated(hash = 717937950)
            public Meizi(Long _id, String source, @NotNull String url) {
                this._id = _id;
                this.source = source;
                this.url = url;
            }
            @Generated(hash = 507723578)
            public Meizi() {
            }
            public Long get_id() {
                return this._id;
            }
            public void set_id(Long _id) {
                this._id = _id;
            }
            public String getSource() {
                return this.source;
            }
            public void setSource(String source) {
                this.source = source;
            }
            public String getUrl() {
                return this.url;
            }
            public void setUrl(String url) {
                this.url = url;
            }
        }

這里要解釋一下生成的三個核心類的作用:
<p>

</p>
- DaoMaster:使用greenDAO的切入點析桥。DaoMaster保存數(shù)據(jù)庫對象(SQLiteDatabase)并管理特定模式的DAO類(而不是對象)。 它具有靜態(tài)方法來創(chuàng)建表或?qū)⑺鼈儎h除艰垂。 其內(nèi)部類OpenHelper和DevOpenHelper是在SQLite數(shù)據(jù)庫中創(chuàng)建模式的SQLiteOpenHelper實現(xiàn)泡仗。一個DaoMaster就代表著一個數(shù)據(jù)庫的連接。
- DaoSession:管理特定模式的所有可用DAO對象猜憎,您可以使用其中一個getter方法獲取娩怎。 DaoSession還為實體提供了一些通用的持久性方法,如插入胰柑,加載截亦,更新,刷新和刪除柬讨。 DaoSession可以讓我們使用一些Entity的基本操作和獲取Dao操作類崩瓤,DaoSession可以創(chuàng)建多個,每一個都是屬于同一個數(shù)據(jù)庫連接的踩官。
- XxxDAO:數(shù)據(jù)訪問對象(DAO)持續(xù)存在并查詢實體却桶。 對于每個實體,GreenDAO生成一個DAO卖鲤。 它比DaoSession有更多的持久化方法肾扰,例如:count,loadAll和insertInTx蛋逾。

  1. 進行增刪改操作集晚;
    • 編寫DaoManager,用于創(chuàng)建數(shù)據(jù)庫区匣、創(chuàng)建數(shù)據(jù)庫表偷拔、包含增刪改查的操作以及數(shù)據(jù)庫的升級。

       /**
        * 創(chuàng)建數(shù)據(jù)庫亏钩、創(chuàng)建數(shù)據(jù)庫表莲绰、包含增刪改查的操作以及數(shù)據(jù)庫的升級
        * Created by Mr.sorrow on 2017/5/5.
        */
       
       public class DaoManager {
           private static final String TAG = DaoManager.class.getSimpleName();
           private static final String DB_NAME = "greendaotest";
       
           private Context context;
       
           //多線程中要被共享的使用volatile關(guān)鍵字修飾
           private volatile static DaoManager manager = new DaoManager();
           private static DaoMaster sDaoMaster;
           private static DaoMaster.DevOpenHelper sHelper;
           private static DaoSession sDaoSession;
       
           /**
            * 單例模式獲得操作數(shù)據(jù)庫對象
            * @return
            */
           public static DaoManager getInstance(){
               return manager;
           }
       
           public void init(Context context){
               this.context = context;
           }
       
           /**
            * 判斷是否有存在數(shù)據(jù)庫,如果沒有則創(chuàng)建
            * @return
            */
           public DaoMaster getDaoMaster(){
               if(sDaoMaster == null) {
                   DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME, null);
                   sDaoMaster = new DaoMaster(helper.getWritableDatabase());
               }
               return sDaoMaster;
           }
       
           /**
            * 完成對數(shù)據(jù)庫的添加姑丑、刪除蛤签、修改、查詢操作栅哀,僅僅是一個接口
            * @return
            */
           public DaoSession getDaoSession(){
               if(sDaoSession == null){
                   if(sDaoMaster == null){
                       sDaoMaster = getDaoMaster();
                   }
                   sDaoSession = sDaoMaster.newSession();
               }
               return sDaoSession;
           }
       
           /**
            * 打開輸出日志震肮,默認關(guān)閉
            */
           public void setDebug(){
               QueryBuilder.LOG_SQL = true;
               QueryBuilder.LOG_VALUES = true;
           }
       
           /**
            * 關(guān)閉所有的操作称龙,數(shù)據(jù)庫開啟后,使用完畢要關(guān)閉
            */
           public void closeConnection(){
               closeHelper();
               closeDaoSession();
           }
       
           public void closeHelper(){
               if(sHelper != null){
                   sHelper.close();
                   sHelper = null;
               }
           }
       
           public void closeDaoSession(){
               if(sDaoSession != null){
                   sDaoSession.clear();
                   sDaoSession = null;
               }
           }
       }
      
    • 編寫XxxDaoUtil戳晌,用于完成對某一張數(shù)據(jù)表的具體操作——ORM操作鲫尊。以創(chuàng)建MeiziDaoUtil為例:

       public class MeiziDaoUtils {
           private static final String TAG = MeiziDaoUtils.class.getSimpleName();
           private DaoManager mManager;
       
           public MeiziDaoUtils(Context context){
               mManager = DaoManager.getInstance();
               mManager.init(context);
           }
       
           /**
            * 完成meizi記錄的插入,如果表未創(chuàng)建沦偎,先創(chuàng)建Meizi表
            * @param meizi
            * @return
            */
           public boolean insertMeizi(Meizi meizi){
               boolean flag = false;
               flag = mManager.getDaoSession().getMeiziDao().insert(meizi) == -1 ? false : true;
               Log.i(TAG, "insert Meizi :" + flag + "-->" + meizi.toString());
               return flag;
           }
      
           /**
            * 插入多條數(shù)據(jù)疫向,在子線程操作
            * @param meiziList
            * @return
            */
           public boolean insertMultMeizi(final List<Meizi> meiziList) {
               boolean flag = false;
               try {
                   mManager.getDaoSession().runInTx(new Runnable() {
                       @Override
                       public void run() {
                           for (Meizi meizi : meiziList) {
                               mManager.getDaoSession().insertOrReplace(meizi);
                           }
                       }
                   });
                   flag = true;
               } catch (Exception e) {
                   e.printStackTrace();
               }
               return flag;
           }
      
           /**
            * 修改一條數(shù)據(jù)
            * @param meizi
            * @return
            */
           public boolean updateMeizi(Meizi meizi){
               boolean flag = false;
               try {
                   mManager.getDaoSession().update(meizi);
                   flag = true;
               }catch (Exception e){
                   e.printStackTrace();
               }
               return flag;
           }
      
           /**
            * 刪除單條記錄
            * @param meizi
            * @return
            */
           public boolean deleteMeizi(Meizi meizi){
               boolean flag = false;
               try {
                   //按照id刪除
                   mManager.getDaoSession().delete(meizi);
                   flag = true;
               }catch (Exception e){
                   e.printStackTrace();
               }
               return flag;
           }
       
           /**
            * 刪除所有記錄
            * @return
            */
           public boolean deleteAll(){
               boolean flag = false;
               try {
                   //按照id刪除
                   mManager.getDaoSession().deleteAll(Meizi.class);
                   flag = true;
               }catch (Exception e){
                   e.printStackTrace();
               }
               return flag;
           }
      
           /**
            * 查詢所有記錄
            * @return
            */
           public List<Meizi> queryAllMeizi(){
               return mManager.getDaoSession().loadAll(Meizi.class);
           }
       
           /**
            * 根據(jù)主鍵id查詢記錄
            * @param key
            * @return
            */
           public Meizi queryMeiziById(long key){
               return mManager.getDaoSession().load(Meizi.class, key);
           }
      
           /**
            * 使用native sql進行查詢操作
            */
           public List<Meizi> queryMeiziByNativeSql(String sql, String[] conditions){
               return mManager.getDaoSession().queryRaw(Meizi.class, sql, conditions);
           }
      
           /**
            * 使用queryBuilder進行查詢
            * @return
            */
           public List<Meizi> queryMeiziByQueryBuilder(long id){
               QueryBuilder<Meizi> queryBuilder = mManager.getDaoSession().queryBuilder(Meizi.class);
               return queryBuilder.where(MeiziDao.Properties._id.eq(id)).list();
           }
       }
      
    • 單個插入操作:

       case R.id.insert:
          mMeiziDaoUtils.insertMeizi(new Meizi(null, "Google",
                   "http://7xi8d6.48096_n.jpg"));
           break;
      
    • 批量插入操作:

       List<Meizi> meiziList = new ArrayList<>();
        meiziList.add(new Meizi(null, "HuaWei",
                "http://7xi8d648096_n.jpg"));
        meiziList.add(new Meizi(null, "Apple",
                "http://7xi8d648096_n.jpg"));
        meiziList.add(new Meizi(null, "MIUI",
                "http://7xi8d648096_n.jpg"));
        mMeiziDaoUtils.insertMultMeizi(meiziList);
      
    • 單個更改操作:(其中原有的數(shù)據(jù)都不會保存,如果新建的對象有屬性沒有設置豪嚎,則會為空搔驼,不為空的字段沒有設置,則報錯)

       Meizi meizi = new Meizi();
       meizi.set_id(1002l);
       meizi.setUrl("http://baidu.jpg");
       mMeiziDaoUtils.updateMeizi(meizi);
      
    • 刪除某條記錄操作:

       Meizi meizi1 = new Meizi();
       meizi1.set_id(1002l);
       mMeiziDaoUtils.deleteMeizi(meizi1);
      
    • 刪除所有記錄操作:

      mMeiziDaoUtils.deleteAll();
      
  2. 專為查詢單獨列出疙渣;
    • 查詢所有記錄:

       case R.id.checksingle:
           Log.i(TAG, mMeiziDaoUtils.queryMeiziById(1008l).toString());
           break;
      
    • 根據(jù)主鍵查詢記錄:

       case R.id.checkmult:
           List<Meizi> meiziList1 = mMeiziDaoUtils.queryAllMeizi();
           for (Meizi meizi2 : meiziList1) {
               Log.i(TAG, meizi2.toString());
           }
           break;
      
    • 各種條件查詢

      • 使用native sql進行條件查詢:

         case R.id.queryNativeSql:
             String sql = "where _id > ?";
             String[] condition = new String[]{"1008"};
             List<Meizi> meiziList2 = mMeiziDaoUtils.queryMeiziByNativeSql(sql, condition);
             for (Meizi meizi2 : meiziList2) {
                 Log.i(TAG, meizi2.toString());
             }
             break;
        
      • 使用queryBuilder進行條件查詢:
        ???QueryBuilder能夠讓你在不涉及SQL語句的情況下查詢實體匙奴。寫SQL有幾個缺點堆巧,首先是易錯的妄荔,其次是要在運行時才知道有沒有問題(假如屬性名是pid,你寫成了id谍肤,也要到運營時才會崩潰)啦租,QueryBuilder能夠在編譯時檢查錯誤(如屬性的引用是否錯誤)瓷耙。
        ???關(guān)于Api:在org.greenrobot.greendao.query包下铅协,QueryBuilder類中查看其方法;構(gòu)造函數(shù)可以傳遞我們的Xxx實體類型冶伞,查詢方法有很多邏輯的where方法系任。where方法中需要設置WhereCondition類型的條件參數(shù)恳蹲,而在org.greenrobot.greendao包下的Property類中,每一種操作符的方法都返回WhereCondition類型俩滥。獲取Property實例則不需要我們?nèi)プ黾卫伲谖覀兊腦xxDao中已經(jīng)有對應的提供,例如我們這里的MeiziDao.Properties.XXX霜旧。

         List<Meizi> meiziList2 = mMeiziDaoUtils.queryMeiziByQueryBuilder(1008);
         for (Meizi meizi2 : meiziList2) {
             Log.i(TAG, meizi2.toString());
         }
        

???LazyList懶加載是指一次性查完數(shù)據(jù)保存在內(nèi)存中错忱,然后關(guān)閉所有連接,再次查詢時從內(nèi)存中獲取挂据。一般查詢大數(shù)據(jù)量時用以清。

五、Demo下載

???????源碼鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末崎逃,一起剝皮案震驚了整個濱河市掷倔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌个绍,老刑警劉巖勒葱,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勺像,死亡現(xiàn)場離奇詭異,居然都是意外死亡错森,警方通過查閱死者的電腦和手機吟宦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涩维,“玉大人殃姓,你說我怎么就攤上這事⊥卟” “怎么了蜗侈?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長睡蟋。 經(jīng)常有香客問我踏幻,道長,這世上最難降的妖魔是什么戳杀? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任该面,我火速辦了婚禮,結(jié)果婚禮上信卡,老公的妹妹穿的比我還像新娘隔缀。我一直安慰自己,他們只是感情好傍菇,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布猾瘸。 她就那樣靜靜地躺著,像睡著了一般丢习。 火紅的嫁衣襯著肌膚如雪牵触。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天咐低,我揣著相機與錄音揽思,去河邊找鬼。 笑死渊鞋,一個胖子當著我的面吹牛绰更,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锡宋,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼儡湾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了执俩?” 一聲冷哼從身側(cè)響起徐钠,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎役首,沒想到半個月后尝丐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體显拜,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年爹袁,在試婚紗的時候發(fā)現(xiàn)自己被綠了远荠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡失息,死狀恐怖譬淳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盹兢,我是刑警寧澤邻梆,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站绎秒,受9級特大地震影響浦妄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜见芹,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一剂娄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辆童,春花似錦宜咒、人聲如沸惠赫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽儿咱。三九已至庭砍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間混埠,已是汗流浹背怠缸。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钳宪,地道東北人揭北。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像吏颖,于是被迫代替她去往敵國和親搔体。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理半醉,服務發(fā)現(xiàn)疚俱,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 一缩多、關(guān)于greenDAO greenDAO應該算是當前最火的數(shù)據(jù)庫開源框架了呆奕,它是一個將對象映射到SQLite數(shù)據(jù)...
    當幸福來敲門58閱讀 13,845評論 3 19
  • 1. Java基礎部分 基礎部分的順序:基本語法养晋,類相關(guān)的語法,內(nèi)部類的語法梁钾,繼承相關(guān)的語法绳泉,異常的語法,線程的語...
    子非魚_t_閱讀 31,581評論 18 399
  • 類的屬性和實例變量是兩個概念 類的屬性聲明通過關(guān)鍵字@property聲明姆泻, 編譯器在編譯階段將自動:1.為屬性創(chuàng)...
    羚君閱讀 500評論 0 0
  • 雪地飛狐 2016-8-19 10:39 一 老師被學生直呼其名 這種情況圈纺,我本人到目前為止還沒有遇到過。但見過不...
    雪地飛狐閱讀 407評論 2 5