Android数据库框架——GreenDao轻量级的对象关系映射框架,永久告别sqlite
前不久,我在写了ORMLite这个框架的博文
但是对于我个人来说,我可能更加倾向于用GreenDao,所以今天也为大家带来了GreenDao的详细博客,希望大家喜欢,之前也详细介绍了ORM的思想,如果不明白可以先看一下前面的博文,这里就不多赘述了,我们新建一个工程
一.相关介绍
- 官方网站 : http://greendao-orm.com/
- Github : https://github.com/greenrobot/greenDAO
传说中的优点
- 最大性能(最快的 Android ORM)
- 易于使用API
- 高度优化
- 最小内存消耗
那我们可以先来看看怎么集成吧!
首先,我们查看Github上的集成步骤,先添加依赖
我们要添加
compile ‘org.greenrobot:greendao:2.2.1‘
- 1
同时也要添加java的项目包
compile ‘org.greenrobot:greendao-generator:2.2.0‘
- 1
紧接着,我们在main目录下创建一个文件夹java-gen
然后继续在配置文件中添加
//仓库
sourceSets{
main{
java.srcDirs = [‘src/main/java‘,‘src/main/java-gen‘]
}
}
- 1
- 2
- 3
- 4
- 5
- 6
最后,新建一个Module,选择JAVA Library,创建成功后,我们在他的build.gradle下添加
compile ‘org.greenrobot:greendao-generator:2.2.0‘
- 1
二.实体类
到这里,我们的初步集成算是完成了,是不是比较麻烦,我们看
她说现在去看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(1, "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");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
写完这个时候我们要注意了,我们不能直接去运动这个工程,我们要单独编译这个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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
这个类能初始化数据库的很多操作,不过这样还不够,我们需要再写个实在点的操作类,现在只是单单实现一个插入的动作
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) != -1 ? true : false;
return flag;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
五.插入
OK,那我们先去看看sql的插入是怎么做的,定义一个button
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加数据" />
- 1
- 2
- 3
- 4
- 5
我们只需要看他的点击事件就可以了
case R.id.btn_add:
dbUtils = new CommonUtils(this);
Student student = new Student();
student.setName("lgl");
student.setAge(18);
student.setAddress("北京");
dbUtils.insertStudent(student);
break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
我们一运行之后,就可以在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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
我们可以去验证一下吧,那首先先去写一个button吧
<Button
android:id="@+id/btn_add_mult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="批量添加数据" />
- 1
- 2
- 3
- 4
- 5
这样,我们就可以直接看他的点击事件了
case R.id.btn_add_mult:
List<Student> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student studentlist = new Student();
studentlist.setName("lgl" + i);
studentlist.setAge(18 + i);
studentlist.setAddress("北京" + i);
list.add(studentlist);
}
dbUtils.inserMultStudent(list);
break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
我们现在把数据库导出来看看
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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
OK,我们去验证一下,写个按钮咯?
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="修改一条数据" />
- 1
- 2
- 3
- 4
- 5
直接看点击事件
case R.id.btn_update:
Student studentupdate = new Student();
//根据ID来修改
studentupdate.setId((long) 1);
//把年龄改成100岁
studentupdate.setAge(100);
dbUtils.updateStudent(studentupdate);
break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
很好,很强势,我们导出数据库,看看有没有修改成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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
这样就写个按钮
<Button
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除一条数据" />
- 1
- 2
- 3
- 4
- 5
OK,点击事件是比较简单的
case R.id.btn_delete:
Student studentdelete = new Student();
studentdelete.setId((long) 3);
dbUtils.deleteStudent(studentdelete);
break;
- 1
- 2
- 3
- 4
- 5
我们要删除的是他ID为3的数据,那我们运行
可以看到,ID为3的数据已经不见了
九.查询
OK,增删查改我们只剩下查询了,我们先来看一下怎么查询一条语句,写个方法
/**
* 查询单条
*
* @param key
* @return
*/
public Student listOneStudent(long key) {
return daoManager.getDaoSession().load(Student.class, key);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
我们再定义一个button
<Button
android:id="@+id/btn_load"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询一条数据" />
- 1
- 2
- 3
- 4
- 5
这样我们就可以去查询了
case R.id.btn_load:
Log.i(TAG, dbUtils.listOneStudent(5) + "");
break;
- 1
- 2
- 3
十.全部查询
全部查询比较简单
/**
* 全部查询
*
* @return
*/
public List<Student> listAll() {
return daoManager.getDaoSession().loadAll(Student.class);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
直接去调用就好了
case R.id.btn_load_all:
List<Student> lists = dbUtils.listAll();
Log.i(TAG, lists.toString());
break;
- 1
- 2
- 3
- 4
十一.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(19)).where(StudentDao.Properties.Address.like("北京")).list();
Log.i(TAG, list + "");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
不难看出,使用起来是比较方便的,我们可以无限的加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) != -1 ? 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(19)).where(StudentDao.Properties.Address.like("北京")).list();
Log.i(TAG, list + "");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
OK,这个博客算是结束了,我们下一篇再聊