GreenRobot新作 - ObjectBox
?ObjectBox是GreenRobot的新作NoSQL存儲(chǔ)系統(tǒng)。GreenRobot稱它是目前性能最好且易用的 NoSQL 數(shù)據(jù)庫(kù),且優(yōu)于其它數(shù)據(jù)庫(kù) 5~15 倍的性能。
特性
首先為什么我們需要這個(gè)數(shù)據(jù)庫(kù), GreenRobot 介紹了它的5個(gè)特性:
- 快 : 比測(cè)試過的其它數(shù)據(jù)庫(kù)快 5~15 倍
- 面向?qū)ο蟮?API : 沒有 rows、columns 和 SQL,完全面向?qū)ο蟮?API
- 即時(shí)的單元測(cè)試 : 因?yàn)樗强缙脚_(tái)的,所以可以在桌面運(yùn)行單元測(cè)試
- 簡(jiǎn)單的線程 : 它返回的對(duì)象可以在任何線程運(yùn)轉(zhuǎn)
- 不需要手動(dòng)遷移 : 升級(jí)是完全自動(dòng)的,不需要關(guān)心屬性的變化以及命名的變化
如何配置與使用呢?
首先在android項(xiàng)目根目錄的build.gradle文件中配置:
buildscript { repositories { jcenter() mavenCentral() maven { url "http://objectbox.net/beta-repo/" } } dependencies { classpath 'io.objectbox:objectbox-gradle-plugin:0.9.11' } }
App目錄下build.gradle應(yīng)該這樣配置:
apply plugin: 'com.android.application' apply plugin: 'io.objectbox' repositories { jcenter() mavenCentral() maven { url "http://objectbox.net/beta-repo/" } } dependencies { compile 'io.objectbox:objectbox-android:0.9.11' }
配置完后,你可能會(huì)得到以下一段錯(cuò)誤提示:
Warning:Conflict with dependency 'com.google.code.findbugs:jsr305'. Resolved versions for app (3.0.1) and test app (2.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.
解決方案如下, app的build.gradle下做配置:
android{
...
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}
...
}
那么我們又如何使用ObjectBox呢?
在 Application 中初始化
// 在 Application 中初始化
boxStore = MyObjectBox.builder().androidContext(App.this).build();
Entity
Entity 是需要被持久化保存的類。我們需要用 @Entity 注解來標(biāo)注它,屬性通常 private 修飾,然后會(huì)自動(dòng)生成 getter 、 setter
ID
在 ObjectBox 中,每一個(gè) Entity 都需要有 long 類型的 ID 屬性,我們需要使用 @Id 來標(biāo)注它。
@Entity
public classUser{
@Id
private long id;
...
}
ID 有以下需要注意的點(diǎn):
- 0 代表對(duì)象還沒被持久化,一個(gè)新的需要被持久化的對(duì)象的 Id 應(yīng)為 0
- 如果需要使用服務(wù)器端已經(jīng)存在的 Id,需要這樣標(biāo)記
@Id(assignable = true),這樣就不會(huì)檢查插入對(duì)象時(shí)對(duì)象的 Id
屬性
通常我們不需要在屬性上使用注解,除非:
- 需要指定特殊的存儲(chǔ)在數(shù)據(jù)庫(kù)中時(shí)的名稱,使用
@Property注解 - 不需要持久化該屬性,使用
@Transient注解
@Entity
public classUser{
@Property(nameInDb = "USERNAME")
private String name;
@Transient
private int tempUsageCount;
...
}
索引
使用 @Index 注解可以生成索引,加快查詢速度。
@Entity
public classUser{
@Id
private Long id;
@Index
private String name;
}
關(guān)聯(lián)
使用 @Relation 注解可以標(biāo)注關(guān)聯(lián)關(guān)系。
一對(duì)一
customId 屬性會(huì)自動(dòng)生成。
@Entity
public classOrder{
@Id long id;
long customerId;
@Relation
Customer customer;
}
@Entity
public classCustomer{
@Id long id;
}
一對(duì)多
一對(duì)多的時(shí)候,只能修飾 List。
@Entity
public classCustomer{
@Id long id;
// References the ID property in the *Order* entity
@Relation(idProperty = "customerId")
List<Order> orders;
}
@Entity
public classOrder{
@Id long id;
long customerId;
@Relation Customer customer;
}
Query
首先要獲取 Box 對(duì)象,然后通過 QueryBuilder 查詢,以下是一個(gè)找出 firstName 是 Joe 的例子:
Box<User> userBox = boxStore.boxFor(User.class);
List<User> joes = userBox.query().equal(User_.firstName, "Joe").build().find();
QueryBuilder 還提供了形如 greater 、 startsWith 等 API,使用非常方便。
分頁(yè)
Query<User> query = userBox.query().equal(UserProperties.FirstName, "Joe").build();
List<User> joes = query.find(10 /** offset by 10 */, 5 /** limit to 5 results */);
-
offset: 查詢的第一項(xiàng)的 offset -
limit: 查詢多少項(xiàng)
查詢的結(jié)果可以直接修改和刪除,會(huì)同步數(shù)據(jù)庫(kù)更改結(jié)果。
Insert
Box 對(duì)象的 put 方法可以插入對(duì)象,通常主鍵的值是 0,如果服務(wù)器已經(jīng)確定主鍵了需要添加注解標(biāo)注。
性能對(duì)比
筆者簡(jiǎn)單測(cè)試了一下和 Realm 對(duì)比的性能差距,以 2000 個(gè)簡(jiǎn)單對(duì)象為例:
Insert
生成 2000 個(gè)對(duì)象一次性插入數(shù)據(jù)庫(kù)
- objectbox:39ms
- realm:127ms
Query
查詢所有 2000 條數(shù)據(jù)
- objectbox:22ms
- realm:40ms
Delete
刪除所有 2000 條數(shù)據(jù)
- objectbox:20ms
- realm:47ms
PS: 陷阱,使用ObjectBox時(shí),不應(yīng)該再在以下地方添加ndk配置,否則的話可能會(huì)出現(xiàn) cannot find libobjectbox.so的錯(cuò)誤。
android{
...
defaultConfig{
ndk{ ... } //此處應(yīng)該注釋掉,不然會(huì)報(bào)錯(cuò)找不到 **libobjectbox.so**
}
...
}