本文作者:speedy
CSDN 專欄:blog.csdn.net/speedystone…
掘金專欄:juejin.im/post/595a12…
前言
在 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 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 ordersWithThisProduct;
}
@Entity
public class JoinProductsWithOrders {
@Id private Long id;
private Long productId;
private Long orderId;
}
@Entity
public class Order {
@Id private Long id;
} 複製程式碼
二、自定義型別
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 {
@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;
}
} 複製程式碼
三、複雜查詢
a, 條件查詢
方法一:
List joes = userDao.queryRaw("where AGE>?","10");//查詢年齡大於10的使用者 複製程式碼
方法二:
List 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): 設定起始位置
// 從第二條記錄開始查詢5條記錄
List list = userDao.queryBuilder()
.offset(2)
.limit(5)
.list(); 複製程式碼
d, 懶載入
LazyList lazyList = userDao.queryBuilder().listLazy();
for (User u:lazyList) {
Log.i(TAG, "使用者名稱:"+u.getName());
}
lazyList.close(); //不再使用時必須關閉,否則會導致資料庫遊標未關閉,從而導致記憶體洩漏 複製程式碼
LazyList 是 GreenDao 實現的集合類,實現了 List 介面,所以,直接把 LazyList 當做List 來使用即可,
public class LazyList implements List, Closeable {
//省略了具體實現
} 複製程式碼
注意: LazyList 不再使用時必須呼叫用 close() 方法關閉,否則會導致記憶體洩漏 。
lazyList.close();複製程式碼
e, 故障查詢
很多時候我們在查詢的時候不能查詢到我們期望的結果,這個時候我們可以通過修改 QueryBuilder 的兩個靜態成員變數來列印 SQL 日誌,便於排查問題。
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;複製程式碼
f, 多表聯合查詢
QueryBuilder queryBuilder = userDao.queryBuilder();
queryBuilder.join(Address.class, AddressDao.Properties.userId)
.where(AddressDao.Properties.Street.eq("Sesame Street"));
List 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("");
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;
}
}複製程式碼
3, 獲取 RxDao
User user = new User();
user.setUserId(10);
user.setName("小紅");
user.setAge(18);
DaoSession daoSession = ((MyApp) getApplication()).getDaoSession();
RxDao userDao = daoSession.getUserDao().rx();
userDao.insert(user)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
@Override
public void call(User user) {
Log.i(TAG, "儲存成功 ");
}
}); 複製程式碼