1. 程式人生 > >Android框架之路——GreenDao3.2.2的使用

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

一、簡介

GreenDAO是一個開源的安卓ORM框架,能夠使SQLite資料庫的開發再次變得有趣。它減輕開發人員處理低階資料庫需求,同時節省開發時間。 SQLite是一個令人敬畏的內嵌的關係資料庫,編寫SQL和解析查詢結果是相當乏味和耗時的任務。通過將Java物件對映到資料庫表(稱為ORM,“物件/關係對映”),GreenDAO可以將它們從這些對映中釋放出來,這樣,您可以使用簡單的面向物件的API來儲存,更新,刪除和查詢資料庫。

簡單的講,GreenDAO 是一個將物件對映到 SQLite 資料庫中的輕量且快速的 ORM 解決方案。

二、ORM概念

物件-關係對映(OBJECT/RELATIONALMAPPING,簡稱ORM),是隨著面向物件的軟體開發方法發展而產生的。用來把物件模型表示的物件對映到基於SQL的關係模型資料庫結構中去。這樣,我們在具體的操作實體物件的時候,就不需要再去和複雜的 SQL 語句打交道,只需簡單的操作實體物件的屬性和方法。ORM 技術是在物件和關係之間提供了一條橋樑,前臺的物件型資料和資料庫中的關係型的資料通過這個橋樑來相互轉化。

簡單的講,就是JavaBean和我們的資料庫進行一個關係對映,一個例項物件對應資料庫的一條記錄,每個物件的屬性則對應著資料庫表的欄位。

三、新增依賴

// 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:指定資料庫schema版本號,遷移等操作會用到;
    • daoPackage:通過gradle外掛生成的資料庫相關檔案的包名,預設為你的entity所在的包名;
    • targetGenDir:自定義生成資料庫檔案的目錄,可以將生成的檔案放到我們的java目錄中,而不是build中,這樣就不用額外的設定資源目錄了。
  2. 通過GreenDao3註解的語法來定義我們的一個數據庫實體類及其資料庫操作方法;

    • 我們先生成一個實體類——Meizi,包含id、來源、和圖片url地址;

      public class Meizi {
      
          private String _id;
          private String source;
          private String url;
      }
      
    • 通過添加註解為我們的Meizi實體類生成對應的資料庫操作方法;

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

      這裡的幾個註解含義:

      •  @Entity:將我們的java普通類變為一個能夠被greenDAO識別的資料庫型別的實體類;
      •  @nameInDb:在資料庫中的名字,如不寫則為實體中類名;
      •  @Id:選擇一個long / Long屬性作為實體ID。 在資料庫方面,它是主鍵。 引數autoincrement是設定ID值自增;
      •  @NotNull:使該屬性在資料庫端成為“NOT NULL”列。 通常使用@NotNull標記原始型別(long,int,short,byte)是有意義的;
      •  @Transient:表明這個欄位不會被寫入資料庫,只是作為一個普通的java類欄位,用來臨時儲存資料的,不會被持久化。
    • 通過點選AndroidStudio中的MakeProject,便發現GreenDao為我們的Meizi實體類生成了對應的Getter、Setter方法以及倆個建構函式,同時在我們配置的com.ping.greendao.gen包下生成了三個對應類檔案DaoMaster、DaoSession和MeiziDao,之後所有相關的資料庫操作都依靠這三個檔案了;

      @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;
          }
      }
      

      這裡要解釋一下生成的三個核心類的作用:

      • DaoMaster:使用greenDAO的切入點。DaoMaster儲存資料庫物件(SQLiteDatabase)並管理特定模式的DAO類(而不是物件)。 它具有靜態方法來建立表或將它們刪除。 其內部類OpenHelper和DevOpenHelper是在SQLite資料庫中建立模式的SQLiteOpenHelper實現。一個DaoMaster就代表著一個數據庫的連線。
      • DaoSession:管理特定模式的所有可用DAO物件,您可以使用其中一個getter方法獲取。 DaoSession還為實體提供了一些通用的永續性方法,如插入,載入,更新,重新整理和刪除。 DaoSession可以讓我們使用一些Entity的基本操作和獲取Dao操作類,DaoSession可以建立多個,每一個都是屬於同一個資料庫連線的。
      • XxxDAO:資料訪問物件(DAO)持續存在並查詢實體。 對於每個實體,GreenDAO生成一個DAO。 它比DaoSession有更多的持久化方法,例如:count,loadAll和insertInTx。
  3. 進行增刪改操作;

    • 編寫DaoManager,用於建立資料庫、建立資料庫表、包含增刪改查的操作以及資料庫的升級。

      /**
       * 建立資料庫、建立資料庫表、包含增刪改查的操作以及資料庫的升級
       * 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關鍵字修飾
          private volatile static DaoManager manager = new DaoManager();
          private static DaoMaster sDaoMaster;
          private static DaoMaster.DevOpenHelper sHelper;
          private static DaoSession sDaoSession;
      
          /**
           * 單例模式獲得操作資料庫物件
           * @return
           */
          public static DaoManager getInstance(){
              return manager;
          }
      
          public void init(Context context){
              this.context = context;
          }
      
          /**
           * 判斷是否有存在資料庫,如果沒有則建立
           * @return
           */
          public DaoMaster getDaoMaster(){
              if(sDaoMaster == null) {
                  DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME, null);
                  sDaoMaster = new DaoMaster(helper.getWritableDatabase());
              }
              return sDaoMaster;
          }
      
          /**
           * 完成對資料庫的新增、刪除、修改、查詢操作,僅僅是一個介面
           * @return
           */
          public DaoSession getDaoSession(){
              if(sDaoSession == null){
                  if(sDaoMaster == null){
                      sDaoMaster = getDaoMaster();
                  }
                  sDaoSession = sDaoMaster.newSession();
              }
              return sDaoSession;
          }
      
          /**
           * 開啟輸出日誌,預設關閉
           */
          public void setDebug(){
              QueryBuilder.LOG_SQL = true;
              QueryBuilder.LOG_VALUES = true;
          }
      
          /**
           * 關閉所有的操作,資料庫開啟後,使用完畢要關閉
           */
          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,用於完成對某一張資料表的具體操作——ORM操作。以建立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記錄的插入,如果表未建立,先建立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;
          }
      
          /**
           * 插入多條資料,在子執行緒操作
           * @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;
          }
      
          /**
           * 修改一條資料
           * @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);
          }
      
          /**
           * 根據主鍵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);
      
    • 單個更改操作:(其中原有的資料都不會儲存,如果新建的物件有屬性沒有設定,則會為空,不為空的欄位沒有設定,則報錯)

      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();
      
  4. 專為查詢單獨列出

    • 查詢所有記錄:

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

      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能夠在編譯時檢查錯誤(如屬性的引用是否錯誤)。
            關於Api:在org.greenrobot.greendao.query包下,QueryBuilder類中檢視其方法;建構函式可以傳遞我們的Xxx實體型別,查詢方法有很多邏輯的where方法。where方法中需要設定WhereCondition型別的條件引數,而在org.greenrobot.greendao包下的Property類中,每一種操作符的方法都返回WhereCondition型別。獲取Property例項則不需要我們去做,在我們的XxxDao中已經有對應的提供,例如我們這裡的MeiziDao.Properties.XXX。

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

            LazyList懶載入是指一次性查完資料儲存在記憶體中,然後關閉所有連線,再次查詢時從記憶體中獲取。一般查詢大資料量時用。

五、Demo下載

        原始碼連結


個人公眾號:每日推薦一篇技術部落格,堅持每日進步一丟丟…歡迎關注,想建個微信群,主要討論安卓和Java語言,一起打基礎、用框架、學設計模式,菜雞變菜鳥,菜鳥再起飛,願意一起努力的話可以公眾號留言,謝謝…

相關推薦

Android框架——GreenDao3.2.2的使用

一、簡介 GreenDAO是一個開源的安卓ORM框架,能夠使SQLite資料庫的開發再次變得有趣。它減輕開發人員處理低階資料庫需求,同時節省開發時間。 SQLite是一個令人敬畏的內嵌的關係資料庫,編寫SQL和解析查詢結果是相當乏味和耗時的任務。通過將J

Android框架——Fragmentation的使用(流式交互Demo)

mda gpo href AR 之路 top pos font das Android框架之路——Fragmentation的使用(流式交互Demo)Android框架之路——Fragmentation的使用(流式交互Demo)

Android框架——Banner實現輪播圖(RecyclerView新增Header)

一、簡介 Banner能實現迴圈播放多個廣告圖片和手動滑動迴圈等功能。因為原生ViewPager並不支援迴圈翻頁, 要實現迴圈還得需要自己去動手。Banner框架可以進行不同樣式、不同動畫設定, 以及完善的api方法能滿足大部分軟體首頁輪播圖效果的需求。

Android框架——Glide載入圖片(結合RecyclerView、CardView)

Android框架之路——Glide載入圖片 一、簡介: 在泰國舉行的谷歌開發者論壇上,谷歌為我們介紹了一個名叫 Glide 的圖片載入庫,作者是bumptech。這個庫被廣泛的運用在google的開源專案中,包括2014年google I/O大會

Android框架——Retrofit2.0的初窺(包含Gson)

參考部落格: 實現效果:        使用姿勢:    1. 使用教程 新增依賴 compile ‘com.squareup.retrofit2:retrofit:2.2.0’ compile ‘com.squareup.retr

Android框架——ToolBar的使用

參考部落格教程: Demo下載:      下載連結 效果圖: mainActivity secondActivity 使用流程: 修改App的主題樣式,

Android框架——Fragmentation的使用(流式互動Demo)

簡介: YoKey大神的Fragment庫Fragmentation,主要用於現在App經常需要實現的單Activity+多Fragment以及多Activity+多Fragment的形式架構。同時最最重要的是,它幫助我們封裝了很多好用的方法,解決了一些

Android框架——FloatingActionButton使用與ToolBar進階

參考部落格: 效果演示: FAB的相關: app:fabSize設定FloatingActionButton的大小,有兩種賦值分別是 “mini” 和 “normal”,預設是normal; app:backgroundTint:Floa

Android框架——Json解析一篇就夠(原生技術+Gson+FastJson)

原生技術手動解析 將json物件轉換成JavaBean Api介紹(org.json包下) JSONObject(String string) : 建構函式,將json字串解析為json物件. int length() : 得到json物件的長度. Xxx getXxx(String name) : 根

Android框架——聊天Demo實現

一、所用技術 GreenDao儲存聊天資料; RecyclerView根據viewtype顯示聊天介面; butterknife繫結view;    如果這些你還沒有了解,你可以參考這些文章: 二、實現效果 後臺每5s傳送資料過來,儲存到資料

Android學習2)--UI設計實驗——手機資訊頁面

UI設計實驗——手機資訊頁面 實驗目的 1.掌握相對佈局、線性佈局的使用 2.掌握樣式的使用 3.掌握如何對程式進行國際化 實驗環境 裝有Android開發環境的計算機 實驗任務 任務:手機資訊頁面 實驗目的介面 執行效果介面

python-基礎篇2

python10、if else 流程判斷舉例說明1:import getpass #引用getpass這個模塊 _username = "kk" _password = "123456" username = input("username:") password = getpass.getpass("p

python 小白(無編程基礎,無計算機基礎)的開發 輔助知識2 模塊

sys.path 程序啟動 及其 一般來說 adding 名稱空間 nbsp 運行時 strong 一、模塊和命名空間 一般來說,Python程序往往由多個模塊文件構成,通過import語句連接在一起。每個模塊文件是一個獨立完備的變量包,即一個命名空間。一個模塊文件不能看到

Linux學習-Nginx(2)安裝及配置文件篇【23】---20180210

Nginx編譯 Nginx yum安裝 主配置文件分析 Core functionality分 一、Nginx的安裝方法及配置介紹1、yum安裝官方: http://nginx.org/packages/centos/7/x86_64/RPMSFedora-EPEL: http

Day2----Python學習筆記(2

cell 數據類型的轉換 編碼格式 python3 () shel 不能 索引 png 學習路線: Day1    Day2    Day3    Day4    Day5    ...待續  一、簡單回顧一下昨天的內容   1. 昨天了解到了一些編碼的知識 1.1

MySql 學習-高級2

arch light 建立 存在 默認 In view values 菜鳥 目錄: 1.約束 2.ALTER TABLE 3.VIEW 1.約束   說明:SQL約束用於規定表中的數據規則,如果存在違反約束的數據行為,行為會被約束終止,約束可以在建表

MYSQL學習4(2

資料表的基本操作2 (這裡的例子有用到前面1的) 2.檢視資料表結構 2.1查看錶基本結構語句DESCRIBE DESCRIBE/DESC可以檢視欄位的資訊,其中包括:欄位名、欄位資料型別、是否為主鍵、是否有預設值等。語法規則: DESCRIBE 表名;或者簡寫為:DESC 表名; 例:

【視訊回放 | Office高手】第2次課程:Word文件美化

《Office高手之路》第2次課程:Word文件 提示:為了保證學習效果,建議使用電腦觀看。 簡要總結 1.查詢替換的應用 2.字型格式的設定 3.段落格式的設定 4.製表符的應用 5.格式刷的使用 6.標尺的應用 7.頁首頁尾的初步學習 8.換行符的應用 9.排版四大原則

0基礎統計學學習----概率論基礎2

概率與頻率: 頻率: 頻率我們可以把它想象為一個事件發生的次數,或者一個數據組中,某一個數據出現的次數。 概率: 概率我們可以把它想象成為一個事件可能發生的機率,就是概率。通常P來表示概率。 圖上介紹了概率事件的加法運算原理,P表示概率,括號中A+B

深入理解l核心v4l2框架video for linux 2(轉載)

在看了很多關於v4l2驅動的例程之後,想深入研究下linux核心的v4l2框架,順便把這些記錄下來,以備查用。 Video for Linux 2      隨著一些視訊或者影象硬體的複雜化,V4L2驅動也越來越趨於複雜。許多硬體有多個IC,在/dev下生成多