前言
在 Android ORM 框架:GreenDao 使用详解(基础篇) 中,我们了解了 GreenDao 的基本使用,本文我们将深入讲解 GreenDao 的使用 。
一、复杂表结构
a, 使用 @ToOne 建立一对一 ( 1 : 1) 关系
@Entity
public class Order {
@Id
private Long id;
private long customerId;
@ToOne(joinProperty = "customerId")
private Customer customer;
}
@Entity
public class Customer {
@Id
private Long id;
}
b,使用 @ToMany 建立一对多 (1:N ) 关系
@Entity
public class Customer {
@Id
private Long id;
@ToMany(referencedJoinProperty = "customerId")
@OrderBy("date ASC")
private List<Order> orders;
}
@Entity
public class Order {
@Id private Long id;
private Date date;
private long customerId;
}
c, 使用@JoinEntity 建立多对多(N : M)关系
@Entity
public class Product {
@Id private Long id;
@ToMany
@JoinEntity(
entity = JoinProductsWithOrders.class,
sourceProperty = "productId",
targetProperty = "orderId"
)
private List<Order> ordersWithThisProduct;
}
@Entity
public class JoinProductsWithOrders {
@Id private Long id;
private Long productId;
private Long orderId;
}
@Entity
public class Order {
@Id private Long id;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
二、自定义类型
1,GreenDao 默认支持的类型有
boolean, Boolean
int, Integer
short, Short
long, Long
float, Float
double, Double
byte, Byte
byte[]
String
Date
2,通过 @Convert 注解转换数据类型
例如:将枚举类型转换成整形
@Entity
public class User {
@Id
private Long id;
@Convert(converter = RoleConverter.class, columnType = Integer.class)
private Role role;
public enum Role {
DEFAULT(0), AUTHOR(1), ADMIN(2);
final int id;
Role(int id) {
this.id = id;
}
}
public static class RoleConverter implements PropertyConverter<Role, Integer> {
@Override
public Role convertToEntityProperty(Integer databaseValue) {
if (databaseValue == null) {
return null;
}
for (Role role : Role.values()) {
if (role.id == databaseValue) {
return role;
}
}
return Role.DEFAULT;
}
@Override
public Integer convertToDatabaseValue(Role entityProperty) {
return entityProperty == null ? null : entityProperty.id;
}
}
- 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
- 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
三、复杂查询
a, 条件查询
方法一:
List<User> joes = userDao.queryRaw("where AGE>?","10");
方法二:
List<User> joes = userDao.queryBuilder().where(UserDao.Properties.Age.gt("10")).list()
b, 排序
// order by last name
queryBuilder.orderAsc(Properties.LastName)
// in reverse
queryBuilder.orderDesc(Properties.LastName)
// order by last name and year of birth
queryBuilder.orderAsc(Properties.LastName).orderDesc(Properties.YearOfBirth)
c, 分页
limit(int) : 限制查询返回的结果的数量。
offset(int): 设置起始位置
List<User> list = userDao.queryBuilder()
.offset(2)
.limit(5)
.list();
d, 懒加载
LazyList<User> lazyList = userDao.queryBuilder().listLazy()
for (User u:lazyList) {
Log.i(TAG, "用户名:"+u.getName())
}
lazyList.close()
LazyList 是 GreenDao 实现的集合类,实现了 List 接口,所以,直接把 LazyList 当做List 来使用即可,
public class LazyList<E> implements List<E>, Closeable {
}
注意: LazyList 不再使用时必须调用用 close() 方法关闭,否则会导致内存泄漏 。
lazyList.close();
e, 故障查询
很多时候我们在查询的时候不能查询到我们期望的结果,这个时候我们可以通过修改 QueryBuilder 的两个静态成员变量来打印 SQL 日志,便于排查问题。
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
f, 多表联合查询
QueryBuilder<User> queryBuilder = userDao.queryBuilder()
queryBuilder.join(Address.class, AddressDao.Properties.userId)
.where(AddressDao.Properties.Street.eq("Sesame Street"))
List<User> users = queryBuilder.list()
四、混淆配置
### greenDAO 3
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
# If you do not use SQLCipher:
-dontwarn org.greenrobot.greendao.database.**
# If you do not use RxJava:
-dontwarn rx.**
### greenDAO 2
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
五、数据库加密
greenDAO 支持 SQLCipher 直接绑定。
a, 引入依赖:
compile 'net.zetetic:android-database-sqlcipher:3.5.7@aar'
b, 初始化加密数据库
DevOpenHelper helper = new DevOpenHelper(this, "notes-db-encrypted.db");
Database db = helper.getEncryptedWritableDb("<your-secret-password>");
daoSession = new DaoMaster(db).newSession();
c、其他操作和未加密一样(是不是特别简单)
当然,如果你不是使用 GreenDao 数据库,同样可以使用 SQLCipher 加密保护我们的数据,详细请参考 SQLCipher for Android
六,整合 RxJava
Rxjava 的火爆程度已经是如日中天了,GreenDao 对当然也是对提供对 Rxjava 的支持。(比较失望的是目前 GreedDao 仅支持 Rxjava 1,不支持 Rxjava 2)
1,引入 Rxjava 依赖
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.2.9'
3,初始化 GreedDao 配置
public class App extends Application {
/**
* 加密标识符
*/
public static final boolean ENCRYPTED = true;
private DaoSession daoSession;
@Override
public void onCreate() {
super.onCreate();
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this,ENCRYPTED ? "notes-db-encrypted" : "notes-db");
Database db = ENCRYPTED ? helper.getEncryptedWritableDb("super-secret") : helper.getWritableDb();
daoSession = new DaoMaster(db).newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
3, 获取 RxDao
User user = new User()
user.setUserId(10)
user.setName("小红")
user.setAge(18)
DaoSession daoSession = ((MyApp) getApplication()).getDaoSession()
RxDao<User, Long> userDao = daoSession.getUserDao().rx()
userDao.insert(user)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<User>() {
@Override
public void call(User user) {
Log.i(TAG, "保存成功 ")
}
})