市面上的一些數據庫框架:ORMLite、Afinal、ActiveAndroid、SugarORM、GreenDao、Realm
ORMLite
簡單的介紹如下:
- OrmLite
OrmLite 不是 Android 平臺專用的ORM框架,它是Java ORM。支持JDBC連接,Spring以及Android平臺。語法中廣泛使用了註解(Annotation)。
- SugarORM
SugarORM 是 Android 平臺專用ORM。提供簡單易學的APIs。可以很容易的處理1對1和1對多的關係型數據,並通過3個函數save(), delete() 和 find() (或者 findById()) 來簡化CRUD基本操作。
- GreenDAO
當性能很重要時(數據訪問頻繁),GreenDao是一個很快的解決方案,它能夠支持數千條記錄的CRUD每秒,和OrmLite相比,GreenDAO要快幾乎4.5倍。(準確數據請自行benchmark)。
GreenDAO小於100KB,所以對於應用程序APK的大小影響很小。
- Active Android
Active Record(活動目錄)是Yii、Rails等框架中對ORM實現的典型命名方式。Active Android 幫助你以面向對象的方式來操作SQLite。
在你的項目中包含Active Android,你需要在項目的 /libs 目錄下添加一個jar文件。可以從Github中獲取源代碼並使用Maven進行編輯。
- 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類進行增刪查改的時候對應的數據庫也會進行對應的操作