提要
因为最近做个小项目需要用到数据库,考虑使用ObjectBox。因为还是测试版,网上真实使用该数据库的相关资料也很少。根据官方文档遇到了一些问题,所以就想找时间记录下自己的经验,供大家参考。
本文内容摘要:
- 正确的初始化及正常使用
- 数据库关联
简单介绍:
- greenrobot公司出品,greenDao、EventBus同样出自该公司。
- ObjectBox是该公司针对性能提升新出的数据库,据官网称优于对比测试的所有嵌入型数据库5-15倍。
- 当前可在Android、Linux、Windows平台上使用,MacOS和iOS随后跟进。本文为Android平台使用经验。
- 目前最新版本是0.99 (2017.3.07)。
使用
一、初始化
首先:添加依赖
直接从官网拿了,照着操作。
注意:不像其他很多需要初始化的库,ObjectBox在这一步完成后不能直接在Application中进行初始化。
ps:当初没注意文档有没有特殊说明需要先Build,现在是有特殊说明的。当时我是直接去初始化。一直找不到MyObjectBox
这个类,还以为是自己依赖添加有问题。后来看到Alex_Cin的文章才注意到这一点。文章不知道为什么他已经删了。真的帮到我了,感谢。
buildscript {
repositories {
jcenter()
mavenCentral()
maven {
url "http://objectbox.net/beta-repo/"
}
}
dependencies {
classpath 'io.objectbox:objectbox-gradle-plugin:0.9.9'
}
}
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.9'
}
然后:生成实体类,创建一个bean类完成该步骤后需build一下project生成ObjectBox需要的类
bean类中主要是两个注解,@Entity和@Id。
- @Entity加在Bean类上,@Id为必需的一个属性。
- 我不需要id这个属性?还有id我该怎么设置?其实你不用管。
- 在ObjectBox数据库中,0和-1是特殊的不可作为id的值。id为0时表示对象未保存到数据库,会自动为其分配一个id值。默认情况类似id从1开始自增长。因为long类型默认值为0,所以大部分情况你可以不用管id这个属性。
- 最高检查。如果你试图将id值大于当前数据库中id最大值的对象放入数据库,ObjectBox会报错。
- 从其他地方获取id,比如服务器,可以使用
@Id(assignable = true)
,最高检查也不会生效。
- 简单代码示例,直接从官网拿的。
@Entity
public class User {
@Id
private long id;
...
}
最后:真正的初始化
一步一步来的话,就很顺利,这个也没什么好说的。
//自定义的Application里,放一个静态BoxStore对象,用下面的代码赋值。
boxStore = MyObjectBox.builder().androidContext(YourApplication.this).build();
二、增删查改
- 获取到某个数据库,比如获取实体类A的相关数据库:
aBox = ((App) getApplication()).getBoxStore().boxFor(A.class);
- 利用aBox,ObjectBox提供了一系列方便易用的Api。
- 增:
.put()
,参数可以是集合、也可以是单个A对象,单个对象时该Api返回放入数据库后的对象id。 - 删:
.remove()
系列Api,参数可以是对象、对象集合、对象id、对象id集合等,你还可以直接使用removeAll()
来清空某个对象的数据库。不同于一些数据库会返回被删除对象,ObjectBox的删除操作均返回void。 - 查:使用
.query()
获取一个QueryBuilder,使用builder.equal()进行设置匹配。该步可以调用startWith()
等Api进行精确设置。之后进行build()
获取一个Query对象
,然后就可以执行各种花式操作了。下面是Query的一些Api。关于整个查询可以参照官方详细查询操作。注意,查询中设置属性应该使用生成类的属性。比如User生成类为User_,要使用到年龄属性可以使用User_.age()。- 查找:find()、findfirst()、findUnique()。如名字,最后一个是从匹配结果里找出一个独特的,没有或者有多个都返回null。
- 精确查找设置:
query.setParameter()
。 - 分页查询:find(long offset,long limit)方法。offset为偏移量,就是从哪开始,但不会返回这个结果,比如设置10就返回从11开始的数据。limit为最多返回多少数据。
- 直接返回一些计算过的值,该类Api以属性为参数,比如想知道所有用户中年龄最大的可以使用
max(User_.age)
,此外还有min/minDouble、sum/sumDouble、avg、maxDouble等,见名知意。double后缀返回Double类型值。 - 从数据库中删除匹配的对象,可以直接使用query.remove()。
- 增:
三、关联
问题是这样的:
在学校里一个年级对应有很多班,每个班又有很多学生。这时我需要把整个年级作为一个对象存储到数据库,使用ObjectBox需要怎么操作?
第一步,生成基本类
这里生成三个类,Grade.class
、Class.class
、Student.class
。并应用@Entity、@Id这些必要的注解。以及一些与其他实体类不相干的属性可以设置了。现在我们的类大概是这样的(做了整合,真实工程中当然是分开写的)
@Entity
public class Grade {
@Id long id;
//...
}
@Entity
public class Class {
@Id long id;
//...
}
@Entity
public class Student {
@Id long id;
//...
}
第二步,做关联
主要是一个注解@Relation
。
简单提下一对一
我们假设一个年级只能有一个班,则年级和班的类可以写成下面这样
@Entity
public class Grade {
@Id long id;
//...
}
@Entity
public class Class{
@Id long id;
long gradeId;
@Relation
Grade grade;
/--------------------------------------------------/
}
build之后可以通过setGradeId()
和setGrade()
来设置对应关系。效果一样。
一对多
比如,六年级有三个班
- 对于这些班来说,需要一个标记来标识自己是哪个年级的。上边的一对一就是做到了这一点。
- 对于六年级这个年级来说,需要有一个集合属性来保存多个
Class
。这时可以通过给集合里的所有Class
设置统一的gradeId
,来形成一对多的关系。我们首先添加一个classes
的集合属性到Grade
类,然后可以通过为其添加@Relation(idProperty = "gradeId")
注解来实现该功能。
这时候Grade.class
和Class.class
类的代码大概是这样的:
@Entity
public class Grade {
@Id long id;
/--------------------------------------------------/
@Relation(idProperty = "gradeId")
List<Class> classes;
/--------------------------------------------------/
//...
}
@Entity
public class Class{
@Id long id;
long gradeId;
@Relation
Grade grade;
//...
}
所以,最后我们的代码应该是这样子的:
@Entity
public class Grade {
@Id long id;
@Relation(idProperty = "gradeId")
List<Class> classes;
//...
}
@Entity
public class Class{
@Id long id;
//下面两句代码是一对一对应到Grade
long gradeId;
@Relation
Grade grade;
//下面的代码是一对多对应到Student
@Relation(idProperty = "classId")
List<Student> students;
//...
}
@Entity
public class Student{
@Id long id;
//下面两句代码是一对一对应到Class
long classId;
@Relation
Class class;
//...
}
注意
关联相关的属性,不要手动写getter/setter方法,当你build工程的时候,它会自动生成。如果你手动写了getter/setter会报错。
If you would like to keep it, it should be explicitly marked with @Keep annotation. Otherwise please mark it with @Generated annotation
删除自己写的即可。
第三步,代码中使用
- 添加,比如往六年级
grade6
添加一个班级class1
。- 首先如果你没有手动为
grade6
设置id,应该保证你是从数据库中取出的数据,或者先将grade6
使用put()
放入gradeBox
,并获取到返回值id。 - 关联。给
class1
设置gradeId
,class1.setGradeId(gradeId)
; - 存放。将
class1
存到数据库,classBox.put(class1)
- 首先如果你没有手动为
- 删除,调用
box.remove()
系列Api即可。 - 删除全部,如移除六年级
grade6
所有班级可以这样grade6.resetClasses()
。
后记
我目前用到的大概就是这些内容,希望能帮到你。