在项目build文件中
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
classpath "io.objectbox:objectbox-gradle-plugin:2.9.1"
}
在app的build文件中
apply plugin: 'io.objectbox'
设置so库防止LinkageError崩溃
ndk {
//设置支持的SO库架构
abiFilters 'armeabi', "armeabi-v7a"
}
可选:Kotlin
对于使用Kotlin的Android项目,请务必添加kotlin-kapt:
apply plugin: 'kotlin-android' // if using Kotlin
apply plugin: 'kotlin-kapt' // if using Kotlin
apply plugin: 'io.objectbox' // apply last
可选:高级设置
ObjectBox插件使用合理的默认值并自动检测大多数配置。 但是,如果需要,您可以使用高级设置选项配置模型文件路径,MyObjectBox包,启用使用高级设置选项。
Advanced Setup - ObjectBox Docs
@Entity
public class User {
@Id
public long id;
@Index
public String accountNumber;
public String name;
public String password;
}
@Entity批注将Java类User标识为可持久化实体(数据库表名)。
@Id实体必须具有一个long类型的属性才能有效地获取或引用对象。自增id
@Index: 因为在ObjectBox中主键是必须设置为long类型的id, 当我们业务上需要另外主键时, 可以再标注@Index
@NameInDb: 字段在数据库中的命名
@Transient: 忽略字段, 不在表中生成
@ToOne:做一对一的关联注解,例如示例中表示一张学生表(Student)关联一张班级表(Class),此外还有一对多,多对多的关联,例如Class的示例:
@Entity
public class Class{
@Id
long id;
@Backlink(to = "classToOne")
public ToMany<Student> studentEntitys;
}
@ToMany:做一对多的关联注解,如示例中表示一张班级表(Class)关联多张学生表(Student)
@Backlink:表示反向关联
需要注意的是:默认情况下,id是会被objectbox管理的,也就是自增id,如果你想手动管理id需要在注解的时候加上@Id(assignable = true)即可。当你在自己管理id的时候如果超过long的最大值,objectbox 会报错。id=0的表示此对象未被持久化,id的值不能为负数。
MyObjectBox类是objectbox自动生成的,需要通过Build> Make project操作来生成,在此之前,需要创建至少一个带有@Entity注解的实体类,才能正常创建MyObjectBox
public class ObjectBox {
private static BoxStore boxStore;
public static void init(Context context) {
boxStore = MyObjectBox.builder()
.androidContext(context.getApplicationContext())
.build();
}
public static BoxStore get() { return boxStore; }
}
在Application中初始化
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ObjectBox.init(this);
}
}
4.1准备
Box<User> box = ObjectBox.get().boxFor(User.class);
User user=new User();
4.2增
user.accountNumber = "896159476";
user.name = "小工";
user.password = "123456";
box.put(user);
4.3查
List<User> userQuery = box.query().equal(User_.accountNumber,"896159476").build().find();
查找首个名字为Joe,并且其出生日期大于1970年,并且其最后一个名字的第一个字母为O的所有用户
QueryBuilder<User> builder = userBox.query();
builder.equal(User_.firstName, "Joe")
.greater(User_.yearOfBirth, 1970)
.startsWith(User_.lastName, "O");
List<User> youngJoes = builder.build().find();
条件操作符
between :两者之间
contains :包含
equal : 相等
notEqual :不相等
startWith :以什么开头
endWith :以什么结尾
greater :大于
less :小于
in :包含
notIn :不包含
isNull :是否null
isNotNull :是否不null
and :条件与
or :条件或
order :按某属性升序排列返回
orderDesc :按某属性降序返回
4.4删
List<User> userQuery = box.query().equal(User_.accountNumber,"123456").build().find();
box.remove(userQuery.get(0).id);
4.5改
List<User> userQuery = box.query().equal(User_.accountNumber,"123456").build().find();
user.id = userQuery.get(0).id;
user.accountNumber = "123456";
user.name = "小工";
user.password = "123456";
box.put(user);
5.1数据库的数据升级
当我们需要新增和删除字段时,直接操作实体类即可,不需要做特殊的更改
如果需要重命名字段名或实体类名,可以按照如下步骤操作:
第一步:给需要修改的类名加上@UID注解
@Entity
@Uid
public class MyName { ... }
第二步:编译项目,编译将失败,并且会给你一个UID
error: [ObjectBox] UID operations for entity "MyName": [Rename] apply the current UID using @Uid(6645479796472661392L) - [Change/reset] apply a new UID using @Uid(4385203238808477712L)
第三步:将Rename后面的UID放入到要修改的类中:
@Entity
@Uid(6645479796472661392L)
public class MyName { ... }
第四步:进行数据的修改
@Entity
@Uid(6645479796472661392L)
public class MyNewName { ... }
更改数据属性或重命名字段名同理操作。
5.2表关系
@ToOne和@ToMany可以看作JAVA中的T和List的关系,拿班级和学生举例,设置相关的学生对象如下:
Class class = new Class(); //先创建一个班级
Student student = new Student();
student.name = "Jay";
student.classToOne.setTarget(class); //设置一对一的target对象,字段参见以上示例
long studentId = StudentBox.put(student);
获取该学生的班级信息:
Student student = StudentBox.get(studentId);
Class class = student.classToOne.getTarget();
而一对多的关系更为简单,你可以像List集合一样去操作它:
Class class_ = new Class(); //先创建一个班级
Student s1 = new Student(); //添加一个学生
student.name = "Jay";
Student s2 = new Student();
s2.name = "Android";
class_ .studentEntitys.add(s1);
class_ .studentEntitys.add(s2);
Box classBox = BaseApp.getInstence().getBoxStore().boxFor(Class.class);
classBox.put(class);
这样的话一张Class表中就有两个学生表的数据了,查询的话可以获取该Class的实体,随后像遍历List集合一样去遍历studentEntitys字段,objectBox提供的方法和List集合几乎一样,这里就不做示例了。
5.3求和等操作
使用Query对象即可进行求和等操作,通过QueryBuilder的build()方法即可得到。随后调用sumDouble()等方法传入求和条件即可。我们获取实体类或实体类集合也是使用的该对象获取。
复用Query和查询参数Parameters
复用第一个query,通过设置query的参数值,来描述第二个,第三个查询。
Query<User> query = userBox.query().equal(User_.firstName, "").build();
List<User> joes = query.setParameter(User_.firstName, "Joe").find();
List<User> jakes = query.setParameter(User_.firstName, "Jake").find();
限制、偏移和分页(Limit, Offset, and Pagination)
跳过第10条,从第11条开始,查询总数为5的结果
Query<User> query = userBox.query().equal(UserProperties.FirstName, "Joe").build();
List<User> joes = query.find(/** offset by */ 10, /** limit to */ 5 /** results */);
offset :第一个 偏移量结果被跳过。
limit :返回此查询的数量。
懒加载
什么事懒加载?
我指定了查询条件,可以获得大量的数据。但是这些大量的数据获取到,是需要大量的时间。考虑到性能和用户体验,我们通常采取的做法是:这些大量的数据我们先不去全部获取,而是你使用到了具体的某个数据的时候,再去到数据库中获取。
Query提供了findLazy() 和 findLazyCached() 来达到懒加载的目的,这些方法返回了一个加强版的list:LazyList(当你去获取其中摸个元素的时候,它才会主动到数据库中加载数据)
再说下findLazyCached(),如其名,它在内存里面缓存了你从数据库中获取的数据。下次你再起获得它的时候,它直接从缓存里面获取数据,加快数据的命中速度。
聚合函数
有时你不想从查询中返回对象,而是得到一个属性的聚合值。ObjectBox支持以下方法(每个都以属性作为参数):
min / minDouble:查找最小值。
max / maxDouble:查找最大值。
sum / sumDouble:计算所有值的总和。( ? Note: the non-double version detects overflows and throws an exception in that case.)
avg : 计算所有值的平均值(double类型)。
另外,可以直接通过调用count()来获得结果的数量。
示例:查询商品
long unit_id;
if (unitId == null || unitId.equals("")) {
unit_id = 0;
} else {
unit_id = Long.parseLong(unitId);
}
int onsales;
if (state.equals("")) {
onsales = 0;
} else {
onsales = Integer.parseInt(state);
}
Box<Product> box = ObjectBox.get().boxFor(Product.class);
//构造查询条件
QueryBuilder<Product> builder = box.query();
//如果类型为0即全部查询,否则查询该条件
if (category != 0) {
builder.equal(Product_.category, category);
}
if (season != 0) {
builder.equal(Product_.season, season);
}
if (brand != 0) {
builder.equal(Product_.brand, brand);
}
if (gender != 0) {
builder.equal(Product_.gender, gender);
}
if (unit_id != 0) {
builder.equal(Product_.unitId, unit_id);
}
builder.equal(Product_.onsales, onsales);
//多个条件模糊查询输入的文字
builder.contains(Product_.phoneticInitial, prodName)
.or().contains(Product_.productName, prodName)
.or().contains(Product_.phoneticInitialAll, prodName)
.or().contains(Product_.productCode, prodName)
.or().contains(Product_.barcode, prodName);
//分页查询
List<Product> list = builder.build()
.find((currentPage - 1) * pageSize, pageSize);
示例:新增商品
Box<Product> box = ObjectBox.get().boxFor(Product.class);
for (Product product : products) {
box.put(product);
}
示例:修改商品
Box<Product> box = ObjectBox.get().boxFor(Product.class);
Query<Product> query = box.query().equal(Product_.productId, 0).build();
for (Product product : products) {
try {
Product findUnique = query.setParameter(Product_.productId, product.getProductId())
.findUnique();
if (findUnique == null) {
box.put(product);
} else {
findUnique.setMerchantId(product.getMerchantId());
findUnique.setOrgMerchantId(product.getOrgMerchantId());
findUnique.setCoverUrl(product.getCoverUrl());
findUnique.setPhoneticInitial(product.getPhoneticInitial());
findUnique.setPhoneticInitialAll(product.getPhoneticInitialAll());
findUnique.setProductName(product.getProductName());
findUnique.setProductCode(product.getProductCode());
findUnique.setBarcode(product.getBarcode());
findUnique.setEntryPrice(product.getEntryPrice());
findUnique.setWholesalePrice(product.getWholesalePrice());
findUnique.setRetailPrice(product.getRetailPrice());
findUnique.setMerchantPrice(product.getMerchantPrice());
findUnique.setCreateTime(product.getCreateTime());
findUnique.setUpdateTime(product.getUpdateTime());
findUnique.setOnsales(product.getOnsales());
findUnique.setSeason(product.getSeason());
findUnique.setBrand(product.getBrand());
findUnique.setGender(product.getGender());
findUnique.setCategory(product.getCategory());
findUnique.setConstituent(product.getConstituent());
findUnique.setUnitId(product.getUnitId());
box.put(findUnique);
}
} catch (NonUniqueResultException e) {
e.printStackTrace();
long[] ids = query.setParameter(Product_.productId, product.getProductId())
.findIds();
box.remove(ids);
box.put(product);
}
}