Android 数据库之 GreenDAO(二)
一、简介
GreenDAO
是 greenrobot 公司于 2011年7月29日 发布的 对象/关系映射(ORM)。它的本质是为存储在关系数据库SQLite
中的数据提供面向对象的接口。只需为数据模型定义,GreenDAO
将创建 Java 数据对象(实体)和DAO
(数据访问对象)。
- 体积小: 目前 v3.2.2 版本总体积小于260K (不含CPU相关的 native 部分);
- 快速: 目前 Android 领先的 ORM,支持智能生成代码;
- 安全多样:QueryBuilder使用特性常数避免错别字;
- 强大连接:跨实体查询,甚至是复杂关系的链连接;
- 类型灵活:可以使用自定义的类或枚举来表示你的实体数据;
- 支持加密:支持SQLCipher加密数据库。
二、集成
- 在项目级别的
build.gradle
中:
buildscript {
dependencies {
// GreenDao3依赖
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
}
}
- 在模块级别(如
app
模块)的build.gradle
中:
apply plugin: 'com.android.application'
// 或者 apply plugin: 'com.android.library'
apply plugin: 'org.greenrobot.greendao'
dependencies {
compile 'org.greenrobot:greendao:3.2.0'
}
// 以下是按需自行添加
greendao {
// 数据库schema版本,也可以理解为数据库版本号
schemaVersion 1
// 设置DaoMaster 、DaoSession、Dao包名
daoPackage 'com.example.chivas.dbres.db.greendao.dao'
// 设置DaoMaster 、DaoSession、Dao目录
targetGenDir 'src/main/java'
// 设置生成单元测试目录
// targetGenDirTest
// 设置自动生成单元测试用例
// generateTests
}
- 引入Java Bean类(用于映射数据库表结构的各类属性)
@Entity
public class SimpleEntity {
@Id
private long _id;
private boolean simpleBoolean;
private byte simpleByte;
private short simpleShort;
private int simpleInt;
private long simpleLong;
private float simpleFloat;
private double simpleDouble;
private String simpleString;
private byte[] simpleByteArray;
}
三、源码架构分析
- 图例
- 关键类
类名 | 描述 |
---|---|
Entity | 带上了GreenDao注解的Java Bean类,一般来说,没有修改注解情况下这个类的类名会被映射成数据表的表名,而字段名会被映射成数据表的列名(字段上的注解就代表一个约束条件)。 |
EntityDao | 数据库中某一特定表的创建、移除操作管理类,支持数据表的增删改查操作(实际上这些操作都是在执行拼接SQL语句)。 |
DaoMaster | GreenDao的入口类,用于监控某一数据库的创建和版本更新,对其中的表进行创建和删除管理,为每个表创建对应的配置信息。 |
DaoSession | 用于初始化每个表中的缓存,代理了EntityDao,同时封装基础的“增删改查”泛型的方法。可由DaoMaster快速创建多个。 |
DaoConfig | 通过反射方式从EntityDao.Properties提取所有字段,分类缓存。用空间换时间的方式,映射、缓存以提升性能。 |
IdentityScope | 使用了弱引用方式缓存Entity对象,存入LongHashMap或者HashMap中,多个DaoSession对应多个IdentityScope缓存。同一条数据库对象会缓存多份检索操作数据,每一份数据都是单独的一个Java 对象。 |
Propertity | 存储数据库表中每个字段的定义,同时封装了对应的SQL语句方法。 |
WhereCondition | 用于将传入值封装成对应的SQL,有两个具体实现类:StringCondition 和 PropertyCondition。默认用PropertyCondition只需传入对应的参数即可,而StringCondition可以实现自定义的SQL。 |
- 区分
// DaoSession 与 服务器的那个Session有啥联系?
DaoSession会创建Dao对象,然后将其于Dao.class本身形成映射关系并缓存起来,方便快速获取。
服务器的Session用于保存服务端的一些信息,与这里的Session并没有啥联系。
// DaoMaster 都做了什么?
作为入口,在其对象创建时会创建、缓存DaoConfig,而DaoConfig中又会缓存对应于Entity的表列字段分类、
列字段名称等信息,这样既可以方便获取,又能节省获取时的性能损耗。除此之外,它持有数据库对象,
包含创建和删除所有数据表的操作方法,以及创建和管理DaoSession 。
// EntityDao 是怎么实现的?
Dao包含增删改查等对数据表的操作方法,实现过程说白了就是执行拼接的Sql语句进行对应的数据操作。
四、封装GreenDao示例
五、示例代码
public class GreenDaoUtils {
private static Map<String, BaseDao> daoManagers;
@SuppressLint("StaticFieldLeak")
private static Context context;
public static void init(Context context) {
GreenDaoUtils.context = context.getApplicationContext();
if (daoManagers == null) {
daoManagers = new ConcurrentHashMap<>();
}
}
public static SimpleEntityManager getSimpleEntityManager() {
SimpleEntityManager manager = (SimpleEntityManager) daoManagers.get(SIMPLE_ENTITY);
if (null == manager) {
manager = new SimpleEntityManager(context);
daoManagers.put(SIMPLE_ENTITY, manager);
}
return manager;
}
public static void closeAllDataBase() {
if (daoManagers != null && !daoManagers.isEmpty()) {
for (BaseDao baseDao : daoManagers.values()) {
baseDao.closeDataBase();
}
daoManagers = null;
}
}
}
public class SimpleEntityManager extends BaseDao<SimpleEntity> {
public SimpleEntityManager(Context context) {
super(context);
}
}
public class BaseDao<T> {
public static final boolean DEBUG = true;
protected DaoManager mManager;
protected DaoSession mSession;
public BaseDao(Context context) {
mManager = DaoManager.getInstance();
mManager.init(context);
mSession = mManager.getDaoSession();
mManager.setDebug(DEBUG);
}
// 增、删、改、查
}
// 增
public boolean insertObject(T object) {
boolean flag = false;
try {
flag = mManager.getDaoSession().insert(object) != -1;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
// 删
public boolean deleteObject(T object) {
try {
mSession.delete(object);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// 改
public void updateObject(T object) {
if (null == object) {
return;
}
try {
mManager.getDaoSession().update(object);
} catch (Exception e) {
e.printStackTrace();
}
}
// 查
public List<T> queryObject(Class object, String where, String... params) {
Object obj = null;
List<T> objects = null;
try {
obj = mSession.getDao(object);
if (null == obj) {
return new ArrayList<>();
}
objects = mSession.getDao(object).queryRaw(where, params);
} catch (Exception e) {
e.printStackTrace();
}
return objects;
}
六、使用测试
注:可能因为具体测试机器不同,测试结果会有波动。下面的测试结果是用HuaWei Mate10测试的。
七、地址
https://github.com/HongdouHub/testorm