foreword
In Android ORM Framework: GreenDao Detailed Explanation (Basic) , we learned about the basic use of GreenDao. In this article, we will explain the use of GreenDao in depth.
1. Complex table structure
a, use @ToOne to establish a one-to-one (1:1) relationship
@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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
b, use @ToMany to establish a one-to-many (1:N) relationship
@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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
c, use @JoinEntity to establish a many-to-many (N:M) relationship
@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
Second, the custom type
1. The types supported by GreenDao by default are:
boolean, Boolean
int, Integer
short, Short
long, Long
float, Float
double, Double
byte, Byte
byte[]
String
Date
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2. Convert the data type through the @Convert annotation
For example: convert enum type to integer
@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
3. Complex query
a, conditional query
method one:
List<User> joes = userDao.queryRaw("where AGE>?","10");//查询年龄大于10的用户
- 1
Method Two:
List<User> joes = userDao.queryBuilder().where(UserDao.Properties.Age.gt("10")).list();
- 1
b, sort
// 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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
c, pagination
limit(int) : Limit the number of results returned by the query.
offset(int): set the starting position
// 从第二条记录开始查询5条记录
List<User> list = userDao.queryBuilder()
.offset(2)
.limit(5)
.list();
- 1
- 2
- 3
- 4
- 5
d, lazy loading
LazyList<User> lazyList = userDao.queryBuilder().listLazy();
for (User u:lazyList) {
Log.i(TAG, "用户名:"+u.getName());
}
lazyList.close(); //不再使用时必须关闭,否则会导致数据库游标未关闭,从而导致内存泄漏
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
LazyList is a collection class implemented by GreenDao and implements the List interface. Therefore, you can directly use LazyList as a List.
public class LazyList<E> implements List<E>, Closeable {
//省略了具体实现
}
- 1
- 2
- 3
Note : LazyList must be closed with the close() method when it is no longer in use, otherwise it will cause memory leaks.
lazyList.close();
- 1
e, Troubleshooting
Many times we can't query the results we expect when querying. At this time, we can print the SQL log by modifying the two static member variables of QueryBuilder to facilitate troubleshooting.
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
- 1
- 2
f, multi-table joint query
QueryBuilder<User> queryBuilder = userDao.queryBuilder();
queryBuilder.join(Address.class, AddressDao.Properties.userId)
.where(AddressDao.Properties.Street.eq("Sesame Street"));
List<User> users = queryBuilder.list();
- 1
- 2
- 3
- 4
- 5
- 6
Fourth, obfuscated configuration
### 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
5. Database encryption
greenDAO supports SQLCipher direct binding.
a, import dependencies:
compile 'net.zetetic:android-database-sqlcipher:3.5.7@aar'
- 1
b, initialize the encrypted database
DevOpenHelper helper = new DevOpenHelper(this, "notes-db-encrypted.db");
Database db = helper.getEncryptedWritableDb("<your-secret-password>");
daoSession = new DaoMaster(db).newSession();
- 1
- 2
- 3
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'
- 1
- 2
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
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, "保存成功 ");
}
});