Android之greenDao使用

来源:https://www.cnblogs.com/WUXIAOCHANG/archive/2019/04/08/10673557.html
-Advertisement-
Play Games

文章大綱 一、greenDao簡介二、greenDao實戰三、項目源碼下載四、參考文章 一、greenDao簡介 1. 什麼是greenDao GreenDAO是一個開源的Android ORM(“對象/關係映射”),通過ORM(稱為“對象/關係映射”),在我們資料庫開發過程中節省了開發時間。 2. ...


文章大綱

一、greenDao簡介
二、greenDao實戰
三、項目源碼下載
四、參考文章

 

一、greenDao簡介

1. 什麼是greenDao

  GreenDAO是一個開源的Android ORM(“對象/關係映射”),通過ORM(稱為“對象/關係映射”),在我們資料庫開發過程中節省了開發時間。

 

2. GreenDao的官方文檔

(1)GreenDao:適用於您的SQLite資料庫的Android ORM
(2)GreenDao的github地址
(3)GreenDao的Google討論區
(4)GreenDao 加密SQLCipher for Android官方說明地址
(5) GreenDao使用文檔

3. GreenDao原理

  DAO的core library中有以下幾個核心類,也是後面常用到的,先來大概瞭解下他們的結構。

 
  • DaoMaster:Dao中的管理者。它保存了sqlitedatebase對象以及操作DAO classes(註意:不是對象)。其提供了一些創建和刪除table的靜態方法,其內部類OpenHelper和DevOpenHelper實現了
    SQLiteOpenHelper,並創建資料庫的框架。

  • DaoSession:會話層。操作具體的DAO對象(註意:是對象),比如各種getter方法。

  • Daos:實際生成的某某DAO類,通常對應具體的java類,比如NoteDao等。其有更多的許可權和方法來操作資料庫元素。

  • Entities:持久的實體對象。通常代表了一個資料庫row的標準java properties。

4. GreenDao的優點

(1)一個精簡的庫
(2)性能最大化
(3)記憶體開銷最小化
(4)易於使用的 APIs
(5)對 Android 進行高度優化

二、greenDao實戰

1. 添加依賴

在項目的build.gradle添加

 

在app的build.gradle添加

 

具體代碼如下:

apply plugin: 'com.android.application'

//添加greendao相關的plugin
apply plugin: 'org.greenrobot.greendao'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "top.daxianwill.greendaodemo"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    greendao{

        //指定資料庫schema版本號,遷移等操作會用到;
        schemaVersion 1
        //dao的包名,包名預設是entity所在的包;
        daoPackage 'com.greendao.gen'
        //生成資料庫文件的目錄;
        targetGenDir 'src/main/java'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'

    //添加greendao相關依賴
    implementation 'org.greenrobot:greendao:3.2.2'
}

2. 創建實體類

package top.daxianwill.greendaodemo;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.Transient;
import org.greenrobot.greendao.annotation.Generated;

/**
 * 創建資料庫實體類
 *
 *   @Entity 表示這個實體類一會會在資料庫中生成對應的表,

     @Id 表示該欄位是id,註意該欄位的數據類型為包裝類型Long

     @Property 則表示該屬性將作為表的一個欄位,其中nameInDb看名字就知道這個屬性在資料庫中對應的數據名稱。

     @Transient 該註解表示這個屬性將不會作為數據表中的一個欄位。

     @NotNull 表示該欄位不可以為空

     @Unique 表示該欄位唯一
 */
@Entity
public class User {
    @Id
    private Long id;

    @Property(nameInDb = "NAME")
    private String name;

    @Transient
    private int tempUsageCount; // not persisted

    @Generated(hash = 873297011)
    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }
    @Generated(hash = 586692638)
    public User() {
    }
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

註解介紹
(1)@Entity
  用來聲明類實體,表示它將映射為數據表
  @Entity()括弧內可加入更詳細的設置,如:
nameInDb =“TABLE_NAME” ——> 聲明該表的表名,預設取類名
createInDb = true ——> 是否創建表,預設為true
generateConstructors = true ——> 是否生成含所有參數的構造函數,預設為true
generateGettersSetters = true ——> 是否生成getter/setter,預設為true

(2)@Id
  用來聲明某變數為表的主鍵,類型使用Long
  @Id()括弧可加入autoincrement = true表明自增長

(3)@Unique
  用來聲明某變數的值需為唯一值

(4)@NotNull
  用來聲明某變數的值不能為null

(5)@Property
  @Property(nameInDb = “URL”) 用來聲明某變數在表中的實際欄位名為URL

(6)@Transient
  用來聲明某變數不被映射到數據表中

(7)@ToOne、@ToMany
  用來聲明”對一”和“對多”關係,下麵舉例說明:
  學生與學校之間一對多的關係(一個學生對應一個學校,一個學校對應有多個學生)

@Entity
class Student{
    //...省略其他變數
    private long fk_schoolId;//外鍵
 
    @ToOne(joinProperty = "fk_schoolId")
    private School school;
}
 
@Entity
class School{
    //...省略其他變數 
    @ToMany(referencedJoinProperty = "fk_schoolId")
    private List<Student> students;
}

學生與課程之間“多對多”的關係(一個學生對應有多門課程,一門課程對應有多個學生)


@Entity
class Student{
    //...省略其他變數
    @ToMany
    @JoinEntity(
            entity = StudentWithCourse.class,
            sourceProperty = "sId",
            targetProperty = "cId"
    )
    private List<Course> courses;
}
 
@Entity 
class Course{
    //...省略其他變數
    @ToMany
    @JoinEntity(
            entity = StudentWithCourse.class,
            sourceProperty = "cId",
            targetProperty = "sId"
    )
    private List<Course> courses;
}
 
@Entity
class StudentWithCourse{
    @Id
    private Long id;
    private Long sId;
    private Long cId;
}

3. Make Project

  利用上面註解寫好表實體後,通過Build—>Make Project重新編譯項目, 將會在表實體中自動生成構造方法和getter/setter方法,另外在指定(或預設)的包中生成DaoMaster、DaoSession以及表實體對應的Dao(如MovieCollectDao)。
  DaoMaster:用於創建資料庫以及獲取DaoSession
  DaoSession:用於獲取各個表對應的Dao類
  各個表對應的Dao:提供了對錶進行增刪改查的方法

 

4. 進行數據增刪改查

進行操作前,我們先獲取操作的對象

UserDao mUserDao = MyApplication.getInstances().getDaoSession().getUserDao();

進行數據增加

    public void insert(){

        mUser = new User(id++,"any"+id);

        mUserDao.insert(mUser);

        notifyListView();
    }

補充:
(1)上述代碼講的是插入單條數據,插入多條數據方式為:

List<MovieCollect> listUserCollect;
mUserDao.insertInTx(listUserCollect);

(2)插入或替換數據
//插入的數據如果已經存在表中,則替換掉舊數據(根據主鍵來檢測是否已經存在)

MovieCollect userCollect;
mUserDao.insertOrReplace(userCollect);//單個數據

List<MovieCollect> listUserCollect;
mUserDao.insertOrReplace(listUserCollect);//一組數據

進行數據刪除

public void delete(){

        long l = mUserDao.count() - 1;

        mUserDao.deleteByKey(l);

        notifyListView();
    }

補充:
(1)上面代碼講的是刪除一條數據,刪除所有數據方式為:

mUserDao.deleteAll();

(2)刪除多條數據

List<User> listUserCollect;
mUserDao.deleteInTx(listUserCollect);

進行數據修改

    public void update(){

        mUser = new User((long)3,"any0803");

        mUserDao.update(mUser);

        notifyListView();
    }

補充:
(1)上面代碼介紹的是修改單條數據,修改多條數據方式如下:

List<User> listUserCollect;
mUserDao.updateInTx(listUserCollect);

進行數據查詢

public void loadAll(){

        mUserList = mUserDao.loadAll();//查詢所有數據

        notifyListView();
    }

補充:
(1)上面代碼介紹的是查詢所有數據,查詢數據數量方式如下:

int count = mUserDao.count();

(2)精確(where)條件查詢

//查詢電影名為“肖申克的救贖”的電影
MovieCollect movieCollect = 
mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Title.eq("肖申克的救贖")).unique(); 
 
//查詢電影年份為2017的電影
List<MovieCollect> movieCollect =
mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.eq(2017)).list();

(3)模糊查詢(like)

//查詢電影名含有“傳奇”的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Title.like("傳奇")).list();
 
//查詢電影名以“我的”開頭的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Title.like("我的%")).list();

(4)區間查詢

//大於
//查詢電影年份大於2012年的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.gt(2012)).list();
 
//大於等於
//查詢電影年份大於等於2012年的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.ge(2012)).list();
 
//小於
//查詢電影年份小於2012年的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.lt(2012)).list();
 
//小於等於
//查詢電影年份小於等於2012年的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.le(2012)).list();
 
//介於中間
//查詢電影年份在2012-2017之間的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.between(2012,2017)).list();

(5)升序降序

//查詢電影年份大於2012年的電影,並按年份升序排序
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.gt(2012)).orderAsc(MovieCollectDao.Properties.Year).list();
 
//查詢電影年份大於2012年的電影,並按年份降序排序
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.gt(2012)).orderDesc(MovieCollectDao.Properties.Year).list();

(6)and/or

//and
//查詢電影年份大於2012年且電影名以“我的”開頭的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().and(MovieCollectDao.Properties.Year.gt(2012), MovieCollectDao.Properties.Title.like("我的%")).list();
 
//or
//查詢電影年份小於2012年或者大於2015年的電影
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().or(MovieCollectDao.Properties.Year.lt(2012), MovieCollectDao.Properties.Year.gt(2015)).list();

5. 緩存處理

  由於GreenDao預設開啟了緩存,所以當你調用A查詢語句取得X實體,然後對X實體進行修改並更新到資料庫,接著再調用A查詢語句取得X實體,會發現X實體的內容依舊是修改前的。其實你的修改已經更新到資料庫中,只是查詢採用了緩存,所以直接返回了第一次查詢的實體。
解決方法:查詢前先清空緩存,清空方法如下

//清空所有數據表的緩存數據
DaoSession daoSession = MyApplication.getInstances().getDaoSession();
daoSession .clear();
 
//清空某個數據表的緩存數據
UserDao userDao = MyApplication.getInstances().getDaoSession().getUserDao();
userDao.detachAll();

6. 資料庫加密

添加依賴

compile 'net.zetetic:android-database-sqlcipher:3.5.7'//使用加密資料庫時需要添加

獲取操作的資料庫對象

mSQLiteOpenHelper = new MySQLiteOpenHelper(MyApplication.getInstance(), DB_NAME, null);//建庫
mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getEncryptedWritableDb("你的密碼"));//加密
//mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getWritableDatabase());
mDaoSession = mDaoMaster.newSession();

溫馨提示:
(1)使用上面步驟得到的DaoSession進行具體的數據表操作。
(2)如果運行後報無法載入有關so庫的異常,請對項目進行clean和rebuild。

7. 資料庫版本升級

  在版本迭代時,我們經常需要對資料庫進行升級,而GreenDAO預設的DaoMaster.DevOpenHelper在進行數據升級時,會把舊表刪除,然後創建新表,並沒有遷移舊數據到新表中,從而造成數據丟失。
  這在實際中是不可取的,因此我們需要作出調整。下麵介紹資料庫升級的步驟與要點。
第一步
  新建一個類,繼承DaoMaster.DevOpenHelper,重寫onUpgrade(Database db, int oldVersion, int newVersion)方法,在該方法中使用MigrationHelper進行資料庫升級以及數據遷移。
網上有不少MigrationHelper的源碼,這裡採用的是https://github.com/yuweiguocn/GreenDaoUpgradeHelper中的MigrationHelper,它主要是通過創建一個臨時表,將舊表的數據遷移到新表中,大家可以去看下源碼。

public class MyOpenHelper extends DaoMaster.OpenHelper {
    public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }
 
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
 
        //把需要管理的資料庫表DAO作為最後一個參數傳入到方法中
        MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
 
            @Override
            public void onCreateAllTables(Database db, boolean ifNotExists) {
                DaoMaster.createAllTables(db, ifNotExists);
            }
 
            @Override
            public void onDropAllTables(Database db, boolean ifExists) {
                DaoMaster.dropAllTables(db, ifExists);
            }
        },  MovieCollectDao.class);
    }
}

  然後使用MyOpenHelper替代DaoMaster.DevOpenHelper來進行創建資料庫等操作

mSQLiteOpenHelper = new MyOpenHelper(MyApplication.getInstance(), DB_NAME, null);//建庫
mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getWritableDatabase());
mDaoSession = mDaoMaster.newSession();

第二步
  在表實體中,調整其中的變數(表欄位),一般就是新增/刪除/修改欄位。註意:
  (1)新增的欄位或修改的欄位,其變數類型應使用基礎數據類型的包裝類,如使用Integer而不是int,避免升級過程中報錯。
  (2)根據MigrationHelper中的代碼,升級後,新增的欄位和修改的欄位,都會預設被賦予null值。

第三步
  將原本自動生成的構造方法以及getter/setter方法刪除,重新Build—>Make Project進行生成。

第四步
  修改Module下build.gradle中資料庫的版本號schemaVersion ,遞增加1即可,最後運行app

    greendao{
    //資料庫版本號,升級時進行修改
        schemaVersion 2
        //dao的包名,包名預設是entity所在的包;
        daoPackage 'com.greendao.gen'
        //生成資料庫文件的目錄;
        targetGenDir 'src/main/java'
    }

8. 代碼混淆

&emsp;&emsp;在proguard-rules.pro文件中添加以下內容進行混淆配置
# greenDAO開始
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
# If you do not use SQLCipher:
-dontwarn org.greenrobot.greendao.database.**
# If you do not use RxJava:
-dontwarn rx.**
# greenDAO結束
 
 
# 如果按照上面介紹的加入了資料庫加密功能,則需添加一下配置
#sqlcipher資料庫加密開始
-keep  class net.sqlcipher.** {*;}
-keep  class net.sqlcipher.database.** {*;}
#sqlcipher資料庫加密結束

三、項目源碼下載

鏈接:https://pan.baidu.com/s/1uSIvGWPGwIjQp0YTd962AA
密碼:iel2

四、參考文章

    1. https://www.jianshu.com/p/ec37ea99ef69
    2. https://www.jianshu.com/p/53083f782ea2
      3.https://blog.csdn.net/qq_35956194/article/details/79167897

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 每一個資料庫都有自己的數據類型。同樣子redis為我們提供了五種類型的數據——字元串、哈希、列表、集合、有序集合。我們知道關係型數據的數據存放型式是一張二維表。用行和列來表示數據之間的關係。redis是一個nosql資料庫當然不可能在用什麼二維表的形式來表示了。他所有的數據都是以key=value的 ...
  • AI中台是一套完整的智能模型全生命周期管理平臺和服務配置體系,基於數據平臺服務,通過對智能服務的共用復用、對智能服務研發相關角色進行管理,以及研發流程的標準化、自動化,對前臺業務提供個性化智能服務的迅速構建能力支持。 ...
  • 隱式和顯式鎖定:1.innodb是兩階段鎖定協議,隱式鎖定比如在事務的執行過程中.會進行鎖定,鎖只有在commit或rollback的時候,才會同時被釋放2.特定的語句進行顯式鎖定 select ... lock in share mode ; select ... for update,where ...
  • mysql排序問題(對字元串類型數據進行排序)對普通數字字元串欄位排序:select * from qq ORDER BY score*1 DESC,time*1 ASC 一、在mysql操作中我們經常需要對數據進行類型轉換。此時我們應該使用的是cast()或convert()。二、兩者的對比相同點 ...
  • 1.系統要通過嚴格的ACID測試,ACID表示原子性/一致性/隔離性/持久性原子性:一個事務必須被視為一個不可分割的最小工作單元一致性:資料庫總是從一個一致性的狀態轉換到另外一個一致性的狀態隔離性:通常來說一個事務所做的修改在最終提交以前對其他事務是不可見的持久性:一旦事務提交,則其所做的修改就會永 ...
  • 一、Hadoop的數據壓縮 1.概述 在進行MR程式的過程中,在Mapper和Reducer端會發生大量的數據傳輸和磁碟IO,如果在這個過程中對數據進行壓縮處理,可以有效的減少底層存儲(HDFS)讀寫的位元組數,,並且通過減少Map和Reduce階段數據的輸入輸出來提升MR程式的速度,提高了網路帶寬和 ...
  • AWZ愛偽裝 是一款通用的一鍵新機軟體,主要用於對應用偽裝設備參數和清理應用數據,它功能強大,設置豐富,且擁有完整的隨機參數設置、全息備份、虛擬定位功能;支持蘋果iOS越獄設備,不支持安卓系統;暫時支持ios7、8、9、10、11越獄系統,暫時不支持ios11.4之後的越獄(含ios11.4越獄系統 ...
  • 實際上我們通常是使用WebView控制項對本地html進行讀取,這樣就可以體會類似web app和安卓原生混合開發的樂趣了。在讀取本地html並展示在前臺的時候,並不需要在Androidmenifast.xml文件當中設置相應的網路許可權,也不需要設置https協議,因為安卓手機的本地伺服器應該都是基於 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...