Android資料庫架構——GreenDao輕量級的對象關系映射架構,永久告别sqlite

前不久,我在寫了ORMLite這個架構的博文
- Android資料庫架構——ORMLite輕量級的對象關系映射(ORM)Java包
但是對于我個人來說,我可能更加傾向于用GreenDao,是以今天也為大家帶來了GreenDao的詳細部落格,希望大家喜歡,之前也詳細介紹了ORM的思想,如果不明白可以先看一下前面的博文,這裡就不多贅述了,我們建立一個工程
一.相關介紹
- 官方網站 : http://greendao-orm.com/
- Github : https://github.com/greenrobot/greenDAO
傳說中的優點
- 最大性能(最快的 Android ORM)
- 易于使用API
- 高度優化
- 最小記憶體消耗
那我們可以先來看看怎麼內建吧!
- 內建文檔:http://greenrobot.org/greendao/documentation/how-to-get-started/
首先,我們檢視Github上的內建步驟,先添加依賴
我們要添加
同時也要添加java的項目包
緊接着,我們在main目錄下建立一個檔案夾java-gen
然後繼續在配置檔案中添加
//倉庫
sourceSets{
main{
java.srcDirs = ['src/main/java','src/main/java-gen']
}
}
最後,建立一個Module,選擇JAVA Library,建立成功後,我們在他的build.gradle下添加
二.實體類
到這裡,我們的初步內建算是完成了,是不是比較麻煩,我們看
她說現在去看java-gen有生成代碼,實際上我們去看并沒有,因為我們需要NoteDao.java,一個資料緩存對象,那我們需要怎麼去做呢?我們直接在Module的類裡寫了
package com.example;
import de.greenrobot.daogenerator.DaoGenerator;
import de.greenrobot.daogenerator.Entity;
import de.greenrobot.daogenerator.Schema;
public class DaoMaker {
public static void main(String[] args) {
//生成資料庫的實體類,還有版本号
Schema schema = new Schema(, "com.student.entity");
addStudent(schema);
//指定dao
schema.setDefaultJavaPackageDao("com.student.dao");
try {
//指定路徑
new DaoGenerator().generateAll(schema, "D:\\github\\GreenDao\\app\\src\\main\\java-gen");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 建立資料庫的表
*
* @param schema
*/
public static void addStudent(Schema schema) {
//建立資料庫的表
Entity entity = schema.addEntity("Student");
//主鍵 是int類型
entity.addIdProperty();
//名稱
entity.addStringProperty("name");
//年齡
entity.addIntProperty("age");
//位址
entity.addStringProperty("address");
}
}
寫完這個時候我們要注意了,我們不能直接去運動這個工程,我們要單獨編譯這個java類。也就是右鍵
編譯的時間有點點長,我們耐心等待一下就好了,這個時候我們可以看到控制台會列印相關的資訊
這個時候你再去看java-gen目錄,就會有東西了
很nice,這算是前期基本已經完工了,我們可以看他的原型圖
三.核心類
可以看到,GreenDao是有自己建立的類的,我們來看看是什麼類
- DaoSession:會話層,操作具體dDao類,提供了基本的持久化操作方法,比如對實體對象的insert,load,update,refresh,delete的一些操作
- XXDao:實際生成的Dao類,通常對應具體的java類,greenDao為每一個實體類建立一個Dao,他提供了比DaoSession更為具體的付費,比如count,loadALL和inserlnTx,批量插入
- xxEntity:持久的實體對象,通常代表資料庫row标準的java屬性
- Schema:執行個體資料schema,通過schema的版本和預設的java包調用構造器
四.封裝操作類
OK,了解的差不多了,我們就來實戰操作一下吧!實戰的時候,我們不需要在主Activity中放太多的邏輯代碼,全部封裝在一個資料庫的操作類中其實是最好的,是以我們先建立一個類
package com.lgl.greendao;
import android.content.Context;
import com.student.dao.DaoMaster;
import com.student.dao.DaoSession;
import de.greenrobot.dao.query.QueryBuilder;
/**
* 資料庫操作類
* Created by LGL on 2016/7/2.
*/
public class DaoManager {
/**
* 實作功能
* 1.建立資料庫
* 2.建立資料庫的表
* 3.對資料庫的更新
* 4.對資料庫的增删查改
*/
//TAG
public static final String TAG = DaoManager.class.getSimpleName();
//資料庫名稱
private static final String DB_NAME = "greendao.db";
//多線程通路
private volatile static DaoManager manager;
//操作類
private static DaoMaster.DevOpenHelper helper;
//上下文
private Context mContext;
//核心類
private static DaoMaster daoMaster;
private DaoSession daoSession;
//單例模式
public static DaoManager getInstance() {
DaoManager instance = null;
if (manager == null) {
synchronized (DaoManager.class) {
if (instance == null) {
instance = new DaoManager();
manager = instance;
}
}
}
return instance;
}
//傳遞上下文
public void initManager(Context context){
this.mContext = context;
}
/**
* 判斷是否存在資料庫,如果沒有則建立
*
* @return
*/
public DaoMaster getDaoMaster() {
if (daoMaster == null) {
helper = new DaoMaster.DevOpenHelper(mContext, DB_NAME, null);
daoMaster = new DaoMaster(helper.getWritableDatabase());
}
return daoMaster;
}
/**
* 完成對資料庫的操作,隻是個接口
*
* @return
*/
public DaoSession getDaoSession() {
if (daoSession == null) {
if (daoMaster == null) {
daoMaster = getDaoMaster();
}
daoSession = daoMaster.newSession();
}
return daoSession;
}
/**
* 打開輸出日志,預設關閉
*/
public void setDebug() {
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
}
/**
* 關閉DaoSession
*/
public void closeDaoSession() {
if (daoSession != null) {
daoSession.clear();
daoSession = null;
}
}
/**
* 關閉Helper
*/
public void closeHelper() {
if (helper != null) {
helper.close();
helper = null;
}
}
/**
* 關閉所有的操作
*/
public void closeConnection() {
closeHelper();
closeDaoSession();
}
}
這個類能初始化資料庫的很多操作,不過這樣還不夠,我們需要再寫個實在點的操作類,現在隻是單單實作一個插入的動作
package com.lgl.greendao;
import android.content.Context;
import com.student.entity.Student;
/**
* 完成對某一張表的具體操作
* Created by LGL on 2016/7/2.
*/
public class CommonUtils {
private DaoManager daoManager;
//構造方法
public CommonUtils(Context context) {
daoManager = DaoManager.getInstance();
daoManager.initManager(context);
}
/**
* 對資料庫中student表的插入操作
* @param student
* @return
*/
public boolean insertStudent(Student student) {
boolean flag = false;
flag = daoManager.getDaoSession().insert(student) != - ? true : false;
return flag;
}
}
五.插入
OK,那我們先去看看sql的插入是怎麼做的,定義一個button
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加資料" />
我們隻需要看他的點選事件就可以了
case R.id.btn_add:
dbUtils = new CommonUtils(this);
Student student = new Student();
student.setName("lgl");
student.setAge();
student.setAddress("北京");
dbUtils.insertStudent(student);
break;
我們一運作之後,就可以在data/data/報名/databases中找到資料庫了
隻要把他到處到桌面上,就可以檢視資料了
這裡感覺不好,ID應該設定自動增長的對吧!其實隻要不設定ID,他就會自增長的
六.批量插入
插入可以了,我們批量插入就簡單了,CommonUtils中增加與一個方法
/**
* 批量插入
*
* @param students
* @return
*/
public boolean inserMultStudent(final List<Student> students) {
//辨別
boolean flag = false;
try {
//插入操作耗時
daoManager.getDaoSession().runInTx(new Runnable() {
@Override
public void run() {
for (Student student : students) {
daoManager.getDaoSession().insertOrReplace(student);
}
}
});
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
我們可以去驗證一下吧,那首先先去寫一個button吧
<Button
android:id="@+id/btn_add_mult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="批量添加資料" />
這樣,我們就可以直接看他的點選事件了
case R.id.btn_add_mult:
List<Student> list = new ArrayList<>();
for (int i = ; i < ; i++) {
Student studentlist = new Student();
studentlist.setName("lgl" + i);
studentlist.setAge( + i);
studentlist.setAddress("北京" + i);
list.add(studentlist);
}
dbUtils.inserMultStudent(list);
break;
我們現在把資料庫導出來看看
OK,這個非常的nice
七.修改
增删查改嘛,增加說完了,我們來說修改,我們繼續寫修改的方法然後去驗證,這樣對于讀者來說也是閱讀性比較好的
/**
* 修改
* @param student
* @return
*/
public boolean updateStudent(Student student){
boolean flag = false;
try{
daoManager.getDaoSession().update(student);
flag = true;
}catch (Exception e){
e.printStackTrace();
}
return flag;
}
OK,我們去驗證一下,寫個按鈕咯?
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="修改一條資料" />
直接看點選事件
case R.id.btn_update:
Student studentupdate = new Student();
//根據ID來修改
studentupdate.setId((long) );
//把年齡改成100歲
studentupdate.setAge();
dbUtils.updateStudent(studentupdate);
break;
很好,很強勢,我們導出資料庫,看看有沒有修改成100歲
好,那我們可以看到,雖然被改成了100,但是其他字段為null,因為我們修改的時候沒有設定,好吧,設定一下
現在我們可以看到修改了
八.删除
删除就比較簡單了,我們直接寫
/**
* 删除
*
* @param student
* @return
*/
public boolean deleteStudent(Student student) {
boolean flag = false;
try {
//删除指定ID
daoManager.getDaoSession().delete(student);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
這樣就寫個按鈕
<Button
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除一條資料" />
OK,點選事件是比較簡單的
case R.id.btn_delete:
Student studentdelete = new Student();
studentdelete.setId((long) );
dbUtils.deleteStudent(studentdelete);
break;
我們要删除的是他ID為3的資料,那我們運作
可以看到,ID為3的資料已經不見了
九.查詢
OK,增删查改我們隻剩下查詢了,我們先來看一下怎麼查詢一條語句,寫個方法
/**
* 查詢單條
*
* @param key
* @return
*/
public Student listOneStudent(long key) {
return daoManager.getDaoSession().load(Student.class, key);
}
我們再定義一個button
<Button
android:id="@+id/btn_load"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查詢一條資料" />
這樣我們就可以去查詢了
case R.id.btn_load:
Log.i(TAG, dbUtils.listOneStudent() + "");
break;
十.全部查詢
全部查詢比較簡單
/**
* 全部查詢
*
* @return
*/
public List<Student> listAll() {
return daoManager.getDaoSession().loadAll(Student.class);
}
直接去調用就好了
case R.id.btn_load_all:
List<Student> lists = dbUtils.listAll();
Log.i(TAG, lists.toString());
break;
十一.QueryBuilder
作為最重要的查詢,GreenDao肯定是為我們做了很多事情,我們可以翻閱API找到QueryBuilder,這個複合查詢該怎麼用呢?我們根據條件來進行邏輯查詢,原生的有,ORMLite也有,GreenDao也有,我就拿原生的和GreenDao來做對比
/**
* 原生查詢
*/
public void queryNative() {
//查詢條件
String where = "where name like ? and _id > ?";
//使用sql進行查詢
List<Student> list = daoManager.getDaoSession().queryRaw(Student.class, where,
new String[]{"%l%", "6"});
Log.i(TAG, list + "");
}
/**
* QueryBuilder查詢大于
*/
public void queryBuilder() {
//查詢建構器
QueryBuilder<Student> queryBuilder = daoManager.getDaoSession().queryBuilder(Student.class);
//查詢年齡大于19的北京
List<Student> list = queryBuilder.where(StudentDao.Properties.Age.ge()).where(StudentDao.Properties.Address.like("北京")).list();
Log.i(TAG, list + "");
}
不難看出,使用起來是比較友善的,我們可以無限的加where條件查詢
十二.完結
增删查改已經基本上都講完了,那基本上這個架構也OK了,我們來看一下他運作的截圖
邏輯說的還算是比較詳細的,但是這個CommonUtils比較零散
CommonUtils
package com.lgl.greendao;
import android.content.Context;
import android.util.Log;
import com.student.dao.StudentDao;
import com.student.entity.Student;
import java.util.List;
import de.greenrobot.dao.query.QueryBuilder;
/**
* 完成對某一張表的具體操作
* Created by LGL on 2016/7/2.
*/
public class CommonUtils {
//TAG
private static final String TAG = CommonUtils.class.getSimpleName();
private DaoManager daoManager;
//構造方法
public CommonUtils(Context context) {
daoManager = DaoManager.getInstance();
daoManager.initManager(context);
}
/**
* 對資料庫中student表的插入操作
*
* @param student
* @return
*/
public boolean insertStudent(Student student) {
boolean flag = false;
flag = daoManager.getDaoSession().insert(student) != - ? true : false;
return flag;
}
/**
* 批量插入
*
* @param students
* @return
*/
public boolean inserMultStudent(final List<Student> students) {
//辨別
boolean flag = false;
try {
//插入操作耗時
daoManager.getDaoSession().runInTx(new Runnable() {
@Override
public void run() {
for (Student student : students) {
daoManager.getDaoSession().insertOrReplace(student);
}
}
});
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 修改
*
* @param student
* @return
*/
public boolean updateStudent(Student student) {
boolean flag = false;
try {
daoManager.getDaoSession().update(student);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 删除
*
* @param student
* @return
*/
public boolean deleteStudent(Student student) {
boolean flag = false;
try {
//删除指定ID
daoManager.getDaoSession().delete(student);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
//daoManager.getDaoSession().deleteAll(); //删除所有記錄
return flag;
}
/**
* 查詢單條
*
* @param key
* @return
*/
public Student listOneStudent(long key) {
return daoManager.getDaoSession().load(Student.class, key);
}
/**
* 全部查詢
*
* @return
*/
public List<Student> listAll() {
return daoManager.getDaoSession().loadAll(Student.class);
}
/**
* 原生查詢
*/
public void queryNative() {
//查詢條件
String where = "where name like ? and _id > ?";
//使用sql進行查詢
List<Student> list = daoManager.getDaoSession().queryRaw(Student.class, where,
new String[]{"%l%", "6"});
Log.i(TAG, list + "");
}
/**
* QueryBuilder查詢大于
*/
public void queryBuilder() {
//查詢建構器
QueryBuilder<Student> queryBuilder = daoManager.getDaoSession().queryBuilder(Student.class);
//查詢年齡大于19的北京
List<Student> list = queryBuilder.where(StudentDao.Properties.Age.ge()).where(StudentDao.Properties.Address.like("北京")).list();
Log.i(TAG, list + "");
}
}
OK,這個部落格算是結束了,我們下一篇再聊