Android數據庫-- GreenDao

市面上的一些數據庫框架:ORMLite、Afinal、ActiveAndroid、SugarORM、GreenDao、Realm
ORMLite

ActiviteAndroid

SugarORM

GreenDao

Realm

簡單的介紹如下:

  1. OrmLite

OrmLite 不是 Android 平臺專用的ORM框架,它是Java ORM。支持JDBC連接,Spring以及Android平臺。語法中廣泛使用了註解(Annotation)。

  1. SugarORM

SugarORM 是 Android 平臺專用ORM。提供簡單易學的APIs。可以很容易的處理1對1和1對多的關係型數據,並通過3個函數save(), delete() 和 find() (或者 findById()) 來簡化CRUD基本操作。

  1. GreenDAO

當性能很重要時(數據訪問頻繁),GreenDao是一個很快的解決方案,它能夠支持數千條記錄的CRUD每秒,和OrmLite相比,GreenDAO要快幾乎4.5倍。(準確數據請自行benchmark)。
GreenDAO小於100KB,所以對於應用程序APK的大小影響很小。

  1. Active Android

Active Record(活動目錄)是Yii、Rails等框架中對ORM實現的典型命名方式。Active Android 幫助你以面向對象的方式來操作SQLite。
在你的項目中包含Active Android,你需要在項目的 /libs 目錄下添加一個jar文件。可以從Github中獲取源代碼並使用Maven進行編輯。

  1. Realm

Realm 是一個將可以使用的Android ORM,基於C++編寫,直接運行在你的設備硬件上(不需要被解釋),因此運行很快。它同時是開源跨平臺的,iOS的代碼可以在GitHub找到,你還可以找到Objective C以及Swift編寫的Realm使用實例。

 ArrayList<HashMap<String ,String>> list = new ArrayList<HashMap<String, String>>();
39 
40         /**Cursor是結果集遊標,使用Cursou.moveToNext()方法可以從當前行移動到下一行**/
41         Cursor cursor = sqLiteDatabase.rawQuery(sql , bindArgs);
42         int clos_len = cursor.getColumnCount();                 //獲取數據所有列數
43 
44         Log.i("TAG:","querySQLite()方法中獲得總列數clos_len:" + clos_len);
45 
46         boolean isfals = cursor.moveToNext();
47         Log.i("TAG:","isfals值爲:" + isfals);
48 
49         while(cursor.moveToNext()) {                            //循環表格中的每一行
50             Log.i("TAG:","進入到while循環中");
51 
52             HashMap<String , String> map = new HashMap<>();
53             for(int i = 0;i<clos_len;i++){                      //循環表格中的每一列
54                 String clos_name = cursor.getColumnName(i);     //從給定的索引i返回列名
55                 String clos_value = cursor.getString(cursor.getColumnIndex(clos_name));//返回指定的名稱,沒有就返回-1
56                 if(clos_value==null){
57                     clos_value = "";
58                 }
59 
60                 Log.i("TAG:","while循環下面的for循環拿到的數據clos_value爲:"
61                         + cursor.getString(cursor.getColumnIndex(clos_name)));
62 
63                 map.put(clos_name , clos_value);
64             }
65             list.add(map);
66         }
67         return list;

特徵:底層數據庫都是基於開源的SQLite實現,然後在系統層封裝成用於應用層的API,雖然直接使用系統的數據庫API性能很高,但是這些API接口並不是很方便開發者使用,一不小心就會引入Bugs,而且代碼的視覺效果也不好,爲了解決這個問題,一系列的對象關係映射(ORM)框架出現

標題Greendao使用

定義:Greendao的本質是爲存儲在關係數據庫Sqlite中的數據提供面向對象的界面,使用過程中,我們只需定義數據模型,而GreenDAO將創建Java數據對象(實體)和DAO(數據訪問對象)。

特徵:

1.對象/關係映射(ORM Object Relation mapping)

下面是一張對象關係映射圖
在這裏插入圖片描述

2.微小的依賴庫

GreenDao關鍵依賴庫大小不超過100kb,So,也不會出現因爲引入GreenDao而出現65k問題

3.自動生成代碼

使用GreenDao,我們無需關注實體類以及Dao,GreenDao已爲我們自動生成了

4.開源

GreenDao 更新日誌
從2017年開始greendao這個項目已經沒有更新了

使用:
1.配置Gradle

 classpath 'org.greenrobot:greendao-gradle-plugin:3.1.1'//add for greendao

2.添加應用插件

apply plugin: 'org.greenrobot.greendao'//add for greendao

3.添加庫文件

implementation "org.greenrobot:greendao:3.1.1"

4.初始化Greendao的配置

greendao {
		        schemaVersion 66 (當前數據庫版本)
		        daoPackage '包名.db.generator'(生成的Dao,DaoMaster和DaoSession的包名稱)
		        targetGenDir 'src/main/java'(存儲的位置,默認爲構建目錄( build / generated / source / greendao))
   			 }

注意點:當你的數據庫在版本升級的時候會自動把表單進行刪除,所以當你需要自己管理自己的數據庫版本的時候,你需要自己實現DaoMaster.OpenHelper,來進行版本升級管理,有一個開源解決辦法MigrationHelper類,可以用這個

5.編寫所需要的實體類,然後build下就ok

	@Entity(nameInDb = "article_list")
		public class ArticleItemBean implements Parcelable, Cloneable {

		    @Id(autoincrement = true)
		    private Long id;
		    //去掉唯一鍵,
		    @Unique
		    public String newsId = "";
		    public double score;
		    public int template;
		    public int commentNum;
		    //下面我省略了一些代碼,這是greendao自己生成的就不用管了
		    
   	 }

6.通過DaoSession來操作你寫的數據庫,舉個例子根據newsid來進行查找

// 創建數據
        DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(context, "article-db", null);
        DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
        DaoSession daoSession = daoMaster.newSession();
        ArticleItemBeanDao dao = daoSession.getArticleItemBeanDao();
        //查找
          dao.queryBuilder().where(ArticleItemBeanDao.Properties.NewsId.eq(newsId)).unique();
        
        
        DaoMaster:保存數據庫的對象並管理特定模式的Dao類,它具有靜態方法來創建表或者將他們刪除,一個DaoMaster就代表着一個數據庫的連接
        
        DaoSession:管理特定模式的所有可用的Dao類,有一些方法,插入加載更新刪除等操作,DaoSession可以創建多個,每一個都是屬於同一個數據庫的連接
        
        Dao層:數據訪問對象持續存在並查詢實體

7.註解,紅色標記一般是常用的

在這裏插入圖片描述

源碼分析:
1.創建數據庫

DaoMaster.OpenHelper openHelper = new DaoMaster.OpenHelper(){...}
daoMaster = new DaoMaster(openHelper.getWritableDb());

主要看openHelper.getWritableDb()

進入到這個方法如下
public abstract class DatabaseOpenHelper extends SQLiteOpenHelper {
/**
     * Like {@link #getWritableDatabase()}, but returns a greenDAO abstraction of the database.
     * The backing DB is an standard {@link SQLiteDatabase}.
     */
    public Database getWritableDb() {
        return wrap(getWritableDatabase());
    }
}

在往下看getWritableDatabase()

public abstract class SQLiteOpenHelper{
public SQLiteDatabase getWritableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(true);
        }
    }

private SQLiteDatabase getDatabaseLocked(boolean writable) {
        ///這是一系列異常判斷可以直接忽略
                if (version > 0 && version < mMinimumSupportedVersion) {
                    File databaseFile = new File(db.getPath());
                    onBeforeDelete(db);
                    db.close();
                    if (SQLiteDatabase.deleteDatabase(databaseFile)) {
                        mIsInitializing = false;
                        return getDatabaseLocked(writable);
                    } else {
                        throw new IllegalStateException("Unable to delete obsolete database "
                                + mName + " with version " + version);
                    }
                } else {
                    db.beginTransaction();
                    try {
                        if (version == 0) {
                        //這裏就是關鍵的地方創建表單了
                            onCreate(db);
                        } else {
                            if (version > mNewVersion) {
                                onDowngrade(db, version, mNewVersion);
                            } else {
                            //進行升級操作,自己在本地實現
                                onUpgrade(db, version, mNewVersion);
                            }
                        }
                        db.setVersion(mNewVersion);
                        db.setTransactionSuccessful();
                    } finally {
                        db.endTransaction();
                    }
                }
            }

            onOpen(db);

            if (db.isReadOnly()) {
                Log.w(TAG, "Opened " + mName + " in read-only mode");
            }

            mDatabase = db;
            return db;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) {
                db.close();
            }
        }
    }
}

在往下看
public class DaoMaster extends AbstractDaoMaster {
    public static final int SCHEMA_VERSION = 66;

    /** Creates underlying database table using DAOs. */
    public static void createAllTables(Database db, boolean ifNotExists) {
    //創建了一個個的表
        AppListBeanDao.createTable(db, ifNotExists);
    }
到此爲止是把數據庫中的表全部創建完全

然後將數據庫的表與實體類進行關聯
還是回到
daoMaster = new DaoMaster(openHelper.getWritableDb());

進入到DaoMaster的構造方法中
public DaoMaster(Database db) {
        super(db, SCHEMA_VERSION);
        registerDaoClass(AppListBeanDao.class);
    }

進入到registerDaoClass方法裏
public abstract class AbstractDaoMaster {
    protected final Database db;
    protected final int schemaVersion;
    protected final Map<Class<? extends AbstractDao<?, ?>>, DaoConfig> daoConfigMap;

    public AbstractDaoMaster(Database db, int schemaVersion) {
        this.db = db;
        this.schemaVersion = schemaVersion;

        daoConfigMap = new HashMap<Class<? extends AbstractDao<?, ?>>, DaoConfig>();
    }

    protected void registerDaoClass(Class<? extends AbstractDao<?, ?>> daoClass) {
    //這個DaoConfig就是將數據庫和實體類進行了關聯
        DaoConfig daoConfig = new DaoConfig(db, daoClass);
        daoConfigMap.put(daoClass, daoConfig);
    }

2.DaoSeesion

DaoSession對象是通過master.newSession();創建的。DaoSession對象是連接GreenDao框架到SQLite數據庫的紐帶,通過該對象我們可以得到一個與數據庫某個表相關的操作對象xxxDao

daoSession = getDaoMaster().newSession();

進入到newSession()這個方法裏去
public class DaoMaster extends AbstractDaoMaster{
 public DaoSession newSession() {
        return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
    }
}
在往下看

public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
            daoConfigMap) {
        super(db);

        appListBeanDaoConfig = daoConfigMap.get(AppListBeanDao.class).clone();
        appListBeanDaoConfig.initIdentityScope(type);
}

這個daoConfigMap保存了數據庫db與實體類之間的聯繫,當我們用XXXDao類進行增刪查改的時候對應的數據庫也會進行對應的操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章