greenDAO官方主頁(yè):http://greendao-orm.com/
官方主頁(yè)新地址:http://greenrobot.org/greendao/
一、greenDAO是一個(gè)輕量沧竟、快速的ORM解決方案远舅,它將對(duì)象映射到SQLite數(shù)據(jù)庫(kù)。
二僵控、主頁(yè)
greenDAO是一個(gè)幫助Android開發(fā)者將數(shù)據(jù)存到SQLite中的一個(gè)開源項(xiàng)目香到。SQLite是一個(gè)很好的嵌入式關(guān)系數(shù)據(jù)庫(kù)。然而报破,開發(fā)它需要大量額外的工作悠就。編寫SQL和解析查詢結(jié)果是相當(dāng)繁瑣的任務(wù)。greenDAO將會(huì)為你做這些工作:它把Java對(duì)象映射到數(shù)據(jù)表(通常被叫做ORM:https://en.wikipedia.org/wiki/Object-relational_mapping)充易。這樣梗脾,你可以使用一個(gè)簡(jiǎn)單的面向?qū)ο蟮慕涌趤?lái)存儲(chǔ)、更新盹靴、刪除和查詢Java對(duì)象炸茧。將時(shí)間集中在真正的問(wèn)題上瑞妇。
greenDAO的主要設(shè)計(jì)目標(biāo)
·性能最大化(對(duì)于Android來(lái)說(shuō),可能是最快的ORM)
·很容易使用APIs
·對(duì)Android高度優(yōu)化
·最小的內(nèi)存開銷
·較小的文件體積宇立,將注意力集中在重點(diǎn)上
哪些人正在使用greenDAO踪宠?
幾個(gè)頂級(jí)Android應(yīng)用程序都依賴greenDAO。這些應(yīng)用程序中的幾個(gè)超過(guò)了1000萬(wàn)次的安裝妈嘹。這展示了行業(yè)可靠性柳琢。你可以在APPBrain(http://www.appbrain.com/stats/libraries/details/greendao/greendao)上看看目前的統(tǒng)計(jì)數(shù)據(jù)。
三润脸、特性
實(shí)體/關(guān)系映射(ORM)
greenDAO的本質(zhì)是提供一個(gè)保存在關(guān)系型數(shù)據(jù)庫(kù)SQLite中的數(shù)據(jù)的面向?qū)ο蠼涌诩砹场V欢x數(shù)據(jù)模型,然后greenDAO將會(huì)創(chuàng)建Java數(shù)據(jù)對(duì)象(實(shí)體)和DAOs(數(shù)據(jù)訪問(wèn)對(duì)象:https://en.wikipedia.org/wiki/Data_access_object)毙驯。這會(huì)為你節(jié)省很多無(wú)聊的代碼倒堕,那些代碼僅僅是來(lái)回移動(dòng)數(shù)據(jù)。除此之外爆价,greendao提供了一些高級(jí)的ORM功能(http://greendao-orm.com/2011/08/12/greendao-2nd-preview/)垦巴,像一個(gè)session緩存、預(yù)先加載铭段,和活躍實(shí)體骤宣。
性能
greenDAO在性能方面沒(méi)有做任何的妥協(xié)。數(shù)據(jù)庫(kù)擅長(zhǎng)存儲(chǔ)大量數(shù)據(jù)序愚,因此憔披,可以使事件速度加快。使用greenDAO爸吮,大量實(shí)體以每秒數(shù)千實(shí)體(http://greendao-orm.com/2011/10/23/current-performance-figures/)的速率被插入芬膝、更新和加載。
greenDAO和比較流行的ORM工具集的比較:對(duì)于給定相同的實(shí)體形娇,greenDAO插入和更新實(shí)體的速度是ORMLite的兩倍锰霜,并且在加載實(shí)體方面,它的加載速度比ORMLite快4.5倍埂软。在一些特殊的應(yīng)用中锈遥,加載速度是至關(guān)重要的。
除了高性能的greenDAO核心勘畔,像會(huì)話高速緩存和智能熱加載技術(shù)的特性也會(huì)對(duì)性能有額外的提升所灸。
輕量的庫(kù)
greendao核心庫(kù)的大小小于100K,所以添加greendao不會(huì)過(guò)于加大你的APK文件大小炫七。
活動(dòng)實(shí)體
如果你想的話爬立,實(shí)體可以處于“活動(dòng)的”狀態(tài):活動(dòng)實(shí)體可以解決顯而易見的關(guān)系(你只需要調(diào)用getter方法),并且有更新万哪、刪除和刷新方法侠驯,這些方法為持久性功能提供了便利的訪問(wèn)方式抡秆。
協(xié)議緩沖區(qū)支持
greenDAO可以將協(xié)議緩沖區(qū)(protobuf:https://github.com/google/protobuf)對(duì)象直接寫入數(shù)據(jù)庫(kù)中。如果你想通過(guò)protobuf與你的服務(wù)器對(duì)話吟策,你不需要任何的映射儒士。普通實(shí)體的所有持久化操作對(duì)protobuf對(duì)象都是可用的。我們相信這是greenDAO的一個(gè)獨(dú)一無(wú)二的特性檩坚。
代碼生成
greenDAO將會(huì)生成Java數(shù)據(jù)對(duì)象(實(shí)體)和DAO對(duì)象着撩。這些DAO對(duì)象被用來(lái)讓實(shí)體有最好的合理映射射方式。
未來(lái)計(jì)劃:生成adapter匾委,也可能包括一些有CRUD操作的activity拖叙。
開源
greenDAO的源代碼被放在了github(https://github.com/greenrobot/greenDAO)上,并且是完全可用的赂乐。源代碼樹中也包含了一個(gè)JUnit測(cè)試套件薯鳍,它使用了greenDAO所有的特性。因此挨措,它是一個(gè)學(xué)習(xí)greenDAO很好的方式挖滤。
支持
greenDAO開源,且由它的開發(fā)者和社區(qū)共同支持(http://greendao-orm.com/contact-support/)浅役。除此之外壶辜,greenDAO的創(chuàng)造者greenrobot(http://greenrobot.de/)能夠?yàn)槟愕奶厥庑枨筇峁┥虡I(yè)支持。
四担租、使用入門
1、新建項(xiàng)目及在main目錄下新建文件夾java-gen抵怎,用于存放自動(dòng)生成的bean和dao奋救;
2、buid.gradle的配置反惕,添加
sourceSets{
main{
java.srcDirs=['src/main/java','src/main/java-gen']
}
}
以及引用:
compile'de.greenrobot:greendao-generator:2.1.0'
compile'de.greenrobot:greendao:2.1.0'
3尝艘、創(chuàng)建模式對(duì)象,添加數(shù)據(jù)庫(kù)表(實(shí)體類):
importorg.greenrobot.greendao.generator.DaoGenerator;
importorg.greenrobot.greendao.generator.Entity;
importorg.greenrobot.greendao.generator.Schema;
/**
* Created by sunny on 2016/8/12 0012.
*/
public class?Generator{
public static void?main(String[]args)?throws?Exception{
int?version=1;
String?defaultPackage="test.greenDAO.bean";
//創(chuàng)建模式對(duì)象姿染,指定版本號(hào)和自動(dòng)生成的bean對(duì)象的包名
Schema?schema=new?Schema(version,defaultPackage);
//指定自動(dòng)生成的dao對(duì)象的包名,不指定則都DAO類生成在"test.greenDAO.bean"包中schema.setDefaultJavaPackageDao("test.greenDAO.dao");
//添加實(shí)體
addEntity(schema);
//自動(dòng)生成的bean和dao存放的java-gen路徑背亥,注意要改成自己的
String?outDir="E:/test/GreenDAO_sunnyDemo/app/src/main/java-gen";
//調(diào)用DaoGenerator().generateAll方法自動(dòng)生成代碼到之前創(chuàng)建的java-gen目錄下
new?DaoGenerator().generateAll(schema,outDir);
}
private static void?addEntity(Schema?schema) {
//添加一個(gè)實(shí)體,則會(huì)自動(dòng)生成實(shí)體Entity類
Entity?entity=schema.addEntity("Entity");
//指定表名悬赏,如不指定狡汉,表名則為Entity(即實(shí)體類名)
entity.setTableName("student");
//給實(shí)體類中添加屬性(即給test表中添加字段)
entity.addIdProperty().autoincrement();//添加Id,自增長(zhǎng)
entity.addStringProperty("name").notNull();//添加String類型的name,不能為空
entity.addIntProperty("age");//添加Int類型的
ageentity.addDoubleProperty("score");//添加Double的score
}
}
4匆瓜、運(yùn)行Generator類代碼辅肾,會(huì)自動(dòng)生成bean和dao在剛才創(chuàng)建的java-gen文件夾下:
5、新建BaseApplication繼承Application斩祭,并在Manifest文件中配置:
importandroid.app.Application;
importandroid.database.sqlite.SQLiteDatabase;
importtest.greenDAO.dao.DaoMaster;
importtest.greenDAO.dao.DaoSession;
/**
* Created by sunny on 2016/8/12 0020.
*/
public class?BaseApplication?extends?Application{
public?DaoSession?daoSession;
public?SQLiteData basedb;
public?DaoMaster.DevOpenHelper?helper;
public?DaoMaster?daoMaster;
@Override
public void?onCreate() {
super.onCreate();
setupDatabase();
}
private void?setupDatabase() {
//通過(guò)DaoMaster的內(nèi)部類DevOpenHelper兵多,你可以得到一個(gè)便利的SQLiteOpenHelper對(duì)象尖啡。//可能你已經(jīng)注意到了橄仆,你并不需要去編寫「CREATE TABLE」這樣的SQL語(yǔ)句,因?yàn)?/i>greenDAO已經(jīng)幫你做了衅斩。//注意:默認(rèn)的DaoMaster.DevOpenHelper會(huì)在數(shù)據(jù)庫(kù)升級(jí)時(shí)盆顾,刪除所有的表,意味著這將導(dǎo)致數(shù)據(jù)的丟失畏梆。//所以您宪,在正式的項(xiàng)目中,你還應(yīng)該做一層封裝具温,來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的安全升級(jí)蚕涤。
helper=new?DaoMaster.DevOpenHelper(this,Constants.DB_NAME,null);
db=helper.getWritableDatabase();
//注意:該數(shù)據(jù)庫(kù)連接屬于DaoMaster,所以多個(gè)Session指的是相同的數(shù)據(jù)庫(kù)連接铣猩。
daoMaster=new?DaoMaster(db);
daoSession=daoMaster.newSession();
}
public?DaoSession?getDaoSession() {
return?daoSession;
}
public?SQLiteDatabase?getDb() {
return?db;
}
}
6揖铜、接下來(lái)準(zhǔn)備對(duì)數(shù)據(jù)庫(kù)進(jìn)行相關(guān)操作:
(1)先寫一下activity_main的布局:
android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginleft="5dp"
android:layout_marginright="5dp"
android:layout_margintop="10dp"
android:orientation="horizontal">
android:id="@+id/tv_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="id:0">
android:id="@+id/et_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:hint="name">
android:id="@+id/et_age"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:hint="age">
android:id="@+id/et_score"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:hint="score">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:id="@+id/btn_add"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="add">
android:id="@+id/btn_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="delete">
android:id="@+id/btn_update"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="update">
android:id="@+id/btn_query"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="query">
android:id="@+id/lv_list"
android:layout_width="match_parent"
android:layout_height="match_parent">
(2)在MainActivity類上編寫代碼:
importandroid.app.Activity;
importandroid.database.Cursor;
importandroid.database.sqlite.SQLiteDatabase;
importandroid.os.Bundle;
importandroid.text.TextUtils;
importandroid.view.View;
importandroid.widget.AdapterView;
importandroid.widget.EditText;
importandroid.widget.ListView;
importandroid.widget.TextView;
importandroid.widget.Toast;
importjava.util.List;
importde.greenrobot.dao.query.Query;
importtest.greenDAO.bean.Entity;
importtest.greenDAO.dao.EntityDao;
public class?MainActivity?extends?Activity{
privateTextView?tv_id;
private?EditText?et_name;
private?EditText?et_age;
private?EditText?et_score;
private?ListView?lv_list;
private?Cursor?cursor;
private?BaseAdapter?adapter;
private longid;
private?String?name;
private?Integer?age;
private?Double?score;
@Override
protected void?onCreate(Bundle?savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
initView();
//listView列表根據(jù)Id降序排序
String?orderBy=EntityDao.Properties.Id.columnName+"
DESC";
//查詢,得到
cursor?cursor=getDb().query(getEntityDao().getTablename()
,getEntityDao().getAllColumns(),null,null,null,null,orderBy);
//初始化適配器
initAdapter();
}
private void?initView() {
tv_id=(TextView) findViewById(R.id.tv_id);
et_name=(EditText) findViewById(R.id.et_name);
et_age=(EditText) findViewById(R.id.et_age);
et_score=(EditText) findViewById(R.id.et_score);
lv_list=(ListView) findViewById(R.id.lv_list);
}
private void?initAdapter() {
adapter=new?BaseAdapter(this,cursor);
lv_list.setAdapter(adapter);
lv_list.setOnItemClickListener(new?AdapterView.OnItemClickListener() {
@Override
public void?onItemClick(AdapterViewadapterView,Viewview,intposition,longid_index) {
id=cursor.getLong(0);
tv_id.setText("id: "+id);
et_name.setText(cursor.getString(1));
et_age.setText(cursor.getInt(2)+"");
et_score.setText(cursor.getDouble(3)+"");
}
});
}
private?EntityDao?getEntityDao() {
//通過(guò)BaseApplication類提供的getDaoSession()獲取具體Dao
return((BaseApplication)this.getApplicationContext()).getDaoSession().getEntityDao();
}
private?SQLiteDatabase?getDb() {
//通過(guò)BaseApplication類提供的getDb()獲取具體db
return((BaseApplication)this.getApplicationContext()).getDb();
}
/**
*添加*/
public void?addEntity(View?view) {
name=et_name.getText().toString().trim();
age=Integer.parseInt(et_age.getText().toString().trim());
score=Double.parseDouble(et_score.getText().toString().trim());
if(!TextUtils.isEmpty(name)) {
Entity?entity=new?Entity(null,name,age,score);
//面向?qū)ο筇砑颖頂?shù)據(jù)
getEntityDao().insert(entity);
cursor.requery();//刷新
}
else{
Toast.makeText(MainActivity.this,"name不能為空",Toast.LENGTH_SHORT).show();
}
}
/***根據(jù)id刪除*/
public void?deleteEntity(View?view) {
getEntityDao().deleteByKey(id);
cursor.requery();
}
/**
*更新*/
public void?updateList(View?view) {
Entity?entity=new?Entity(id,name,age,score);
getEntityDao().update(entity);
cursor.requery();
}
/**
*根據(jù)name查詢*/
public void?query(View?view) {
if(!TextUtils.isEmpty(name)) {
// Query類代表了一個(gè)可以被重復(fù)執(zhí)行的查詢
Query<Entity>query=getEntityDao().queryBuilder()
.where(EntityDao.Properties.Name.eq(name))
.orderAsc(EntityDao.Properties.Id)
.build();
//查詢結(jié)果以List返回List
count=query.list();
Toast.makeText(MainActivity.this,count.size()+"條數(shù)據(jù)被查到",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"name不能為空",Toast.LENGTH_SHORT).show();
}
}
}