GreenDao 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。它的本质就是提供一个面向对象的接口,使得开发者更加方便地将数据存储到数据库SQLite之中。我们只需要定义数据模型,GreenDao就会为我们生成实体类以及DAOs(data access objects),(在3.0之后不需要我们编写generator而是编写实体类并添加注解,GreenDao会为我们生成schema,以及DAOs)从而避免了开发者编写较多枯燥的数据存储和加载的代码。
GreenDao传送门
GreenDao介绍
在GreenDao中,默认会为每一个实体类建立一张数据表,实体类的每一个属性对应数据表中的一列。
优点
- Android精简的依赖库,方便集成
- 性能最大化
- 内存开销最小化
- 易于使用的APIs
- 对Android进行高度优化
配置
GreenDao3 采用注解方式来定义实体类,通过gradle插件生成相应的代码。
配置插件
在工程根目录下的build.gradle文件里,添加代码:
1 | dependencies { |
配置依赖
在Module下的build.gradle文件里,添加代码:
1 | apply plugin: 'com.android.application' |
- schemaVersion: 数据库版本号,默认为1
- daoPackage: 生成的DAOs、DaoMaster、DaoSession包名;默认为entities(数据库实体类)所在的包名
- targetGenDir: 生成的DAOs、DaoMaster、DaoSession的目录,默认为build/generated/source/greendao
- generateTests: 设置true自动生成单元测试。
- targetGenDirTests: 设置生成单元测试目录。默认为src/androidTest/java
基本用法
实体
创建带注解@Entity的实体类,实体类即数据表;通常(除开带@Transient注解的成员)实体类中成员就是数据库中对应的字段。然后make project
编译项目,实体类会自动生成get、set方法,并且在targetGenDir
目录下的daoPackage
包里,如src/main/java/com/excellence/medical/greendao
,生成DaoMaster、DaoSession、以及AccountDao。
如果想增加或减少数据库字段,删除实体类中自动生成的代码,然后进行增加或减少实体类中的成员。
1 |
|
注解
@Entity
修饰实体类名1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24@Entity(
// schema 名,多个 schema 时设置关联实体。插件产生不支持,需使用产生器
// schema = "myschema",
// 标记一个实体是否处于活动状态,活动实体有 update、delete、refresh 方法。默认为 false
active = false,
// 表名,默认为类名
nameInDb = "Account",
// 定义多列索引
indexes = {
@Index(value = "name DESC", unique = true)
},
// 标记是否创建表,默认 true。多实体对应一个表或者表已创建,不需要 greenDAO 创建时设置 false
createInDb = true,
// 是否产生所有参数构造器。默认为 true。无参构造器必定产生
generateConstructors = true,
// 如果没有 get/set 方法,是否生成。默认为 true
generateGettersSetters = true
)修饰实体类成员
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// 主键,autoincrement设置自增,注意类型是Long,而不是long
@Id(autoincrement = true)
// 唯一,默认索引
@Unique
// 列名-字段名,默认使用变量名。变化:customName --> CUSTOM_NAME
@Property(nameInDb = "USERNAME")
// 索引,unique设置唯一,name设置索引别名
@Index(unique = true)
// 非空
@NotNull
// 忽略,不持久化,即数据表不创建该字段,可用关键字transient替代
@Transient
// 对一,实体属性 joinProperty 对应外联实体ID
@ToOne(joinProperty = "fk_dogId")
// 对多。实体ID对应外联实体属性 referencedJoinProperty
@ToMany(referencedJoinProperty = "fk_userId")
// 对多。@JoinProperty:name 实体属性对应外联实体属性 referencedName
@ToMany(joinProperties = {@JoinProperty(name = "horseName", referencedName = "name")})
// 对多。@JoinEntity:entity 中间表;中间表属性 sourceProperty 对应实体ID;中间表属性 targetProperty 对应外联实体ID
@ToMany
@JoinEntity(entity = JoinUserWithSheep.class, sourceProperty = "uId", targetProperty = "sId")
初始化
在Application中进行初始化,GreenDao打开数据库两种方式:①打开内部(/data/data/xxxpackageNamexxx/
)数据库,②打开外部(其他目录下)数据库
内部数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 注意
DaoMaster.OpenHelper helper = new DaoMaster.DevOpenHelper(this, VOD_DB, null);
mDaoMaster = new DaoMaster(helper.getWritableDatabase());
// 如果想使用Dao,直接用mDaoSession获取对应的Dao来操作
mDaoSession = mDaoMaster.newSession();
// Dao,执行增删改查操作
AccountDao dao = mDaoSession.getAccountDao();
// 如果想使用Sql语句,就使用mDaoDatabase操作
mDaoDatabase = mDaoSession.getDatabase();
// GreenDao有特殊的线程来处理数据库的耗时操作
mAsyncSession = mDaoSession.startAsyncSession();外部数据库
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
35public class DatabaseContext extends ContextWrapper {
private String mDBPath = null;
private DatabaseContext(Context base) {
super(base);
}
public DatabaseContext(Context base, String dbPath) {
super(base);
mDBPath = dbPath;
}
public File getDatabasePath(String name) {
String dbPath = mDBPath + name;
if (FileUtils.isFileExists(dbPath)) {
return new File(dbPath);
} else {
return null;
}
}
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
int flags = SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.NO_LOCALIZED_COLLATORS;
return SQLiteDatabase.openDatabase(getDatabasePath(name).getAbsolutePath(), factory, flags, null);
}
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
int flags = SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.NO_LOCALIZED_COLLATORS;
return SQLiteDatabase.openDatabase(getDatabasePath(name).getAbsolutePath(), factory, flags, errorHandler);
}
}
1 | // 重写传入DaoMaster.DevOpenHelper的Context,即改变数据库的路径 |
注意:
- DaoMaster.DevOpenHelper在数据库升级的时候,会删除所有的表,只能用于Debug调试,正式项目需要封装处理,GreenDao升级请参考:GreenDaoUpgradeHelper
- 如果GreenDao想使用打开多个数据库,可以创建多个DaoMaster.OpenHelper和DaoSession;同时重写onCreate方法,否则每个数据库的表是一样的。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16DaoMaster.OpenHelper helper = new DaoMaster.OpenHelper(this, DB_NAME) {
@Override
public void onCreate(Database db) {
ConfigDao.createTable(db, false);
MemberDao.createTable(db, false);
}
};
mDaoSession = new DaoMaster(helper.getWritableDatabase()).newSession();
DaoMaster.OpenHelper encryptedHelper = new DaoMaster.OpenHelper(this, ENCRYPTED_DB_NAME) {
@Override
public void onCreate(Database db) {
AccountDao.createTable(db, false);
}
};
mEncryptedDaoSession = new DaoMaster(encryptedHelper.getEncryptedWritableDb(getUniquePseudoID())).newSession();
增删改查
使用Dao操作时,数据库里必须有主键,操作才会成功;否则操作无效或达不到预期的结果
GreenDao有一个缓存机制,即把用户插入,更改或查找的实体保存在内存中,当用户下一次查找时先从内存中查找,如果不存在再从数据库中查找,清除缓存使用:
DaoSession.clear()
如果没有主键,则只能使用Sql语句操作数据库,可以参考:Android黄金篇-SQLite数据库
Dao增加
1 | long insert(T entity) // 插入指定实体 |
Dao删除
1 | void deleteAll() // 删除所有 |
Dao修改
1 | void update(T entity) |
Dao查询
1 | java.util.List<T> loadAll() |
QueryBuilder查询
1 | QueryBuilder<T> queryBuilder() // Dao |
示例
1 | mAccountDao.queryBuilder().orderDesc(Properties.Date).limit(1).unique() |
DaoSession异步操作
1 | DaoSession().startAsyncSession().runInTx(new Runnable() { |
DaoSession增删改查
1 | // DaoSession 的方法转换成 Dao 的对应方法执行 |
Query重复查询
1 | // QueryBuilder |
查询结果
1 | // QueryBuilder、Query |
混淆
在混淆文件proguard-rules.pro中添加
1 | ### greenDAO 3 |
@ToOne、@ToMany,1:1、1:n、n:m等多张表关联待续^_^