前言
當初學習Hibernate的時候就非常驚歎這種ORM思想,後來才知道原來Android中也有這種基於ORM思想的開源框架greenDAO。
greenDAO簡介:
簡單的講,greenDAO 是一個將對象映射到 SQLite 數據庫中的輕量且快速的 ORM 解決方案。(greenDAO is a light & fast ORM solution that maps objects to SQLite databases.) Dao全稱是Data Access Object – 數據訪問對象.它是一箇中間件,對象正是通過它才能和數據庫中的表建立聯繫.
什麼是ORM
ORM全稱是Object Relationship Mapping – >對象關係映射,將一個對象映射爲數據庫中的一個表.
對象關係映射,簡單的說就是對象模型和關係模型的一種映射。爲什麼要有這一個映射?因爲現在的開發語言基本是oop的,但是傳統的數據庫卻是關係型的,爲了可以靠貼近面向對象開發,我們想要像操作對象一樣操作數據庫。
ORM 的優點:
- 讓業務代碼訪問對象,而不是數據庫表
- 隱藏面向對象的邏輯SQL查詢詳情
- 無需處理數據庫實現
原生操作數據庫的api的缺點
- 手動拼接sql
- 大量而重複操作數據庫代碼
- 不能自動把數據中的數據映射爲對象
- 沒有實現級聯查詢
主流的ORM框架:
- OrmLiet
- SugarORM
- LitePal
- GreenDAO
對比一個開源框架是否更優秀,一般從下面幾個點來對比
- 性能:性能好一般指的是效率問題
- 文檔:完整的文檔可以避免很多彎路,方便學習
- 流行性:流行證明用戶羣體多,也方便交流合作
- 使用是否簡單:學習成本問題
- 拓展性:拓展性當然需要
greenDao優點:
- 一個精簡的庫
- 性能最大化
- 內存開銷最小化
- 易於使用的 APIs
- 對 Android 進行高度優化
學習方法
對於一項新技術,我本人非常推崇看官方的英文介紹,這樣原汁原味。
- 官網:官網
- 官方github:greenDao
接下來總結下使用步驟。
如何使用GreenDAO
第一步:
使用AS新建項目
app module 裏面添加gradle依賴:
compile 'de.greenrobot:greendao:2.1.0'
不要忘記同步一下
第二步:
在項目中新建一個module,類型選擇Java Library如下圖,命名爲greendaogenerate
在該module的gradle裏面添加依賴:
compile 'de.greenrobot:greendao-generator:2.1.0'
不要忘記同步一下
第三步:
在greendaogenerate這個module裏面D的MyClass類里根據greenDAO的api配置數據庫幫助類以及建表。示例如下:
public class MyClass {
public static void main(String arg[]){
//第一個參數是db的版本號,第二個是生成的包名(該包下若干數據庫操作幫助類)
Schema schema = new Schema(1,"www.greendao.com");
Entity son = schema.addEntity("Son");//創建一個son表
//給son表添加屬性
son.addStringProperty("name");
son.addIntProperty("age");
son.addIdProperty();
Property fatherId = son.addLongProperty("fatherId").getProperty();//設置外鍵
Entity father = schema.addEntity("Father");//創建一個father表
//給father表添加屬性
father.addIdProperty();
father.addStringProperty("name");
father.addIntProperty("age");
son.addToOne(fater,fatherId);//建立關聯
try {
//設置生成的包(www.greendao.com)所存放的的路徑
new DaoGenerator().generateAll(schema,"app/src/main/java");
}catch (Exception e){
e.printStackTrace();
}
}
}
運行該MyClass類,結果如下:
這時候就可以在項目中使用這些由greenDAO框架生成的數據庫幫助類進行測試了。
第四步
在MainActivity裏面具體使用,api的使用示例以及介紹見下面代碼
public class MainActivity extends AppCompatActivity {
//greenDAO提供的幫助類
private DaoMaster master;
private DaoSession session;
private SQLiteDatabase db;
private SonDao sonDao;
private FatherDao fatherDao;
private void openDb(){
//創建一個名爲person.db的數據庫
db = new DaoMaster.DevOpenHelper(MainActivity.this,"person.db",null).getWritableDatabase();
master = new DaoMaster(db);
session = master.newSession();
//獲得son表操作數據庫類的對象
sonDao = session.getSonDao();
//獲得father表操作數據庫類的對象
fatherDao = session.getFatherDao();
}
//插入數據
private void addPerson(){
//下面代碼具體得根據數據庫表的關係,這裏只是示例(son有多個father)
Son son = new Son();
son.setName("nate");
son.setAge(29);
sonDao.insert(son);
Father father = new Father();
father.setName("Tom");
father.setSon(son);
fatherDao.insert(father);
Father father2 = new Father();
father2.setName("Jane");
father2.setSon(son);
fatherDao.insert(father2);
}
//常用api:
//list() 直接取出數據返回一個list並緩存數據
//listLazy() 不直接取出數據返回一個list有緩存,需手動close
//listLazyUncached() 延遲加載返回一個list不緩存數據,需手動close
//listIterator() 遍歷數據,返回一個迭代器
public void queryAll(){
//listLazy()懶加載,多個表級聯查詢使用最佳
List<Son> list = sonDao.queryBuilder().list();//查詢son表中的所有數據,返回集合
for (Son son: list){
Log.d("nate","queryAll() called with: "+son);
}
}
//條件查詢: Eq 查詢
public void queryEq(){
Son nate = sonDao.queryBuilder().where(SonDao.Properties.Name.eq("nate")).unique();
Log.d("nate","queryEq called with:"+ nate);
}
//條件查詢: like 查詢
public void queryLike(){
List data = sonDao.queryBuilder().where(SonDao.Properties.Name.like("nate%")).list();
Log.d("nate","queryEq called with:"+ data);
}
//條件查詢: between 查詢
public void queryBetween(){
List data = sonDao.queryBuilder().where(SonDao.Properties.Age.between(16,20)).list();
Log.d("nate","queryBetween called with:"+ data);
}
//條件查詢: > 大於 查詢
public void queryGt(){
List data = sonDao.queryBuilder().where(SonDao.Properties.Age.gt(16)).list();
Log.d("nate","queryGt called with:"+ data);
}
//條件查詢: < 小於 查詢
public void queryLt(){
List data = sonDao.queryBuilder().where(SonDao.Properties.Age.lt(16)).list();
Log.d("nate","queryLt called with:"+ data);
}
//條件查詢: NotEq 查詢
public void queryNotEq(){
List data = sonDao.queryBuilder().where(SonDao.Properties.Age.notEq(16)).list();
Log.d("nate","queryNotEq called with:"+ data);
}
//條件查詢: GE 大於等於 查詢
public void queryGE(){
List data = sonDao.queryBuilder().where(SonDao.Properties.Age.ge(16)).list();
Log.d("nate","queryGE called with:"+ data);
}
//條件查詢: 排序 查詢
public void queryOrder(){
List data = sonDao.queryBuilder().where(SonDao.Properties.Name.like("nate%"))
.orderDesc(SonDao.Properties.Age).list();
Log.d("nate","queryOrder called with:"+ data);
}
//拼裝sql語句查詢,在api無法滿足查詢需求的情況下使用
public void querySQL(){
List data = sonDao.queryBuilder()
.where(new WhereCondition.StringCondition(
"FATHER_ID IN" +"{SELECT _ID FROM FATHER WHERE AGE <50}"
)).list();
Log.d("nate","querySQL called with:"+ data);
}
//多線程查詢:有興趣可以看源碼
public void queryThread(){
final Query query = sonDao.queryBuilder().build();
new Thread(){
@Override
public void run() {
List data = query.forCurrentThread().list();
Log.d("nate","queryThread called with:"+ data);
}
};
}
//一對多查詢:具體得看數據表關係
public void queryOneToMany(){
List<Son> sons = sonDao.queryBuilder().list();//查詢son表中的所有數據,返回集合
for (Son son:sons){
List<Father> fathers = son.getFathers();
for (Father father:fathers){
Log.d("nate","queryOneToMany() called with: "+son.getName()+" father:"+father.getName());
}
}
}
//一對一查詢:具體得看數據表關係
public void queryOneToOne(){
List<Son> sons = sonDao.queryBuilder().list();//查詢son表中的所有數據,返回集合
for (Son son:sons){
// Log.d("nate","queryOneToOne() called with: "+son.getFather().getName());
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//打開一個數據庫
openDb();
//向數據庫添加person
addPerson();
//設置打印sql語句,方便查看
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
//選擇具體需要的查詢方式測試:如queryOrder
queryOrder();
}
}
對數據庫的操作後必然想查看數據庫的數據是否有變化,但是android查看數據庫不是很方便,幸好有如下這個好工具。
推薦工具:stetho
facebook推出的一款可以在Chrome查看app數據庫的工具
在項目中添加依賴:
compile 'com.facebook.stetho:stetho:1.3.1'
初始化:
public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
Stetho.initializeWithDefaults(this);
}
}
運行App, 打開Chrome輸入chrome://inspect/#devices
chrome會檢測到我們的app,點擊inspect進入查看頁面即可
源碼
Github:GreenDaoDemo
總結
如果學過JavaEE開發,用過Hibernate框架的就會非常容易理解greenDAO框架,兩者都是基於ORM的思想:ORM-對象關係映射,將一個對象映射爲數據庫中的一個表。
此外,學習一個框架,我認爲不只是要學會怎麼使用,最重要的是深入學習這種設計思想以及欣賞底層封裝的代碼的藝術。
感謝
慕課網:nate的 Android框架-GreenDao
後話
歡迎關注我的微信公衆號,不定時推送乾貨