1. 前言
- 主要介绍GreenDao的基本应用。
- 本文资料来源网络公开资源,并根据个人实践见解纯手打整理,如有错误请随时指出。
- 本文主要用于个人积累及分享,文中可能引用其他技术大牛文章(仅引用链接不转载),如有侵权请告知必妥善处理。
2. 应用层原理简介
- 如果这部分看起来感觉抽象难懂,可以先看之后的实操部分,操作一遍之后再回头看,更容易理解此部分。
2.1. 编译后自动注入的文件有哪些
GreenDao是什么我想已无需多解释,关键是了解它在一个事务发起时是怎样去执行一系列代码的。
首先需要了解编译后,GreenDao注入的java文件,主要有哪些,功能是什么。
- 在《GreenDao配置流程》中,schema配置了”daoPackage ‘xx.xxx.xxxxx.greendao.dao’”,当rebuild后,daoPackage所指定的包路径下,我们可以找到自动生成的文件有:
- DaoMaster.java
- 入口类,在任何情况下操作数据库的入口。
- 包含注册XxxxBeanDao类,创建DaoSession实例,操作DatabaseOpenHelper相关的创建表、删除表、更新数据库等操作
- 创建映射关系
- DaoSession.java
- 创建所有Bean类对应的Dao类的实例,完成映射关系
- 每个Bean类对应的Dao类
- 数据库操作类,继承自抽象类AbstractDao
- DaoMaster.java
2.2. 获取一个Dao对象的过程
2.2.1. 代码示例:
DaoSession daoSession = new DaoMaster(new DaoMaster.DevOpenHelper(context, DATA_BASE_NAME).getWritableDb()).newSession();
daoSession.getXxxxBeanDao();
2.2.2. 分段解释创建过程
new DaoMaster(…);
- DaoMaster类的构造方法中,传入的Database实例使用DaoMaster中DevOpenHelper创建,自定义DATA_BASE_NAME
DaoMaster类的构造方法中,进入registerDaoClass(…)方法,可以看到这一操作实际上是将XxxxBeanDao.class加入其抽象父类AbstractDaoMaster的一个map:daoConfigMap中,以把DaoConfig和XxxxBeanDao.class绑定,如下图:
进入DaoConfig类,可以看到,构造方法中代码实际上是一个创建反射机制的过程,这为每个Dao准备好TableName、Property、Pk等一系列参数。每个Dao都将创建一个对应的DaoConfig与之绑定,具体代码不再截图,此类比较简单,但非常重要,后面也会提到。
newSession();
接续上面的内容,回到DaoMaster类,看到daoConfigMap实际是用来创建DaoSession实例的参数,如下图:
创建DaoSession实例时,进入DaoSession类的方法可以看到,调用了daoConfigMap的clone()方法得到所有对应Dao文件的daoConfig,并对其创建缓存入口,这个缓存创建的方法是DaoConfig类中initIdentityScope(IdentityScopeType type)
- 在DaoSession创建中,将创建所有Bean类对应的Dao类的实例,并将XxxxBean.class和对应的Dao类绑定,到此为止GreenDao框架内部基本已完成了对象关系映射处理
此时可以 2.2.1. 的示例代码,可以轻松获得Bean类的操作类XxxxBeanDao的实例。
3. 关于注解
注解的说明,参考官方文档即可,很详细,比较理论的内容貌似没有在这里复述的必要,请参看如下链接:
http://greenrobot.org/greendao/documentation/modelling-entities/
4. 基本应用
将主要通过示例学习
参考官方api:http://greenrobot.org/greendao/documentation/javadoc/
4.1. 创建一个Bean
参看如下PeopleBean.java代码和注释
//注意:准备做数据库存储的Bean,必须添加@Entity注解
@Entity
public class PeopleBean {
@Id
//此处有坑,务必注意
//注意:必须使用包装类型Long,而非基本类型long
private Long id;
@NotNull
private String name;
private int age;
private String province;
private boolean isMale;
@Unique
private String idCard;
//注意:get、set方法,无需自己生成,当此类创建完成后,rebuild项目,将自动生成
//注意:toString是需要自己创建生成的
@Override
public String toString() {
return "PeopleBean{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", province='" + province + '\'' +
", isMale=" + isMale +
", idCard='" + idCard + '\'' +
'}';
}
}
4.2. 获取Dao实例
前提:rebuild项目
4.2.1. 获取DaoSession实例
- 需要注意的是,DaoSession实例包含该项目中所有已被@Entity注解的Bean所创建的Dao类实例,故DaoSession实例最好为单例模式,并加锁
- 或者,将DaoSession创建在该工程的Application类中,也可以形成事实上的单例
这里示例代码展示创建一个单例的工具类,用来获取DaoSession实例:
public class GreenDaoUtil {
private static DaoSession daoSession;
private final static String DATA_BASE_NAME = "test_01.db";
public synchronized static DaoSession getDaoSession(Context context) {
if (daoSession == null) {
daoSession = new DaoMaster(new DaoMaster.DevOpenHelper(context, DATA_BASE_NAME).getWritableDb()).newSession();
}
return daoSession;
}
}
4.2.2. 获取Dao实例
GreenDaoUtil.getDaoSession(activity).getPeopleBeanDao();
4.2.3. Dao操作增删改查示例
复杂应用不一一示例,后面系列文章将逐渐体现
GreenDaoUtil.getDaoSession(activity).getPeopleBeanDao().insert(peopleBean);
GreenDaoUtil.getDaoSession(activity).getPeopleBeanDao().deleteByKey(peopleBean.getId());
GreenDaoUtil.getDaoSession(activity).getPeopleBeanDao().update(peopleBean);
//全部
List<PeopleBean> peopleBeanList = GreenDaoUtil.getDaoSession(activity).getPeopleBeanDao()
.queryBuilder()
.list();
//条件查
List<PeopleBean> peopleBeanList = GreenDaoUtil.getDaoSession(activity).getPeopleBeanDao()
.queryBuilder()
.where(PeopleBeanDao.Properties.Age.gt(30), PeopleBeanDao.Properties.IsMale.eq(true))
.list();
注意:
查询方法返回的 List,从源码上看,永不为null,可以省略对其null判断,直接foreach使用
5. 结语
这一部分基本没有什么坑,比较简单,还是总结下关键点,如下:
- 对于应用层的一些较浅层源码,最好还是熟悉下,便于以后的应用
- 对注解的需要熟悉
- 主键Id,必须包装类Long型,避免各种坑
- DaoSession实例需要单例
- 当Bean变量被改变(或任何涉及数据库的改变),rebuild后数据库对应的表结构也会随之改变,这时必须schema配置必须将schemaVersion +1