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
}
四映砖、解鎖技能
-
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中砂缩,這樣就不用額外的設置資源目錄了作谚。
-
通過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>
- 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蛋逾。
-
進行增刪改操作集晚;
-
編寫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();
-
-
專為查詢單獨列出疙渣;
-
查詢所有記錄:
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下載
???????源碼鏈接