Android ObjectBox开源数据库框架学习笔记
目录
一、前言
二、简介
三、实现步骤
(1)项目引用
(2)建立实体类
(3)开始使用
四、额外扩展
(1)使用ObjectBox帮助类来配置BoxStore
(2)注释说明
(3)查询
(4)Data Observers & Rx
五、练习项目
六、Demo地址
七、内容推荐
一、前言
之前一直在使用GreenDao框架,也感觉很是方便。前段时间又翻了一次官网,突然有了一个意外收获——ObjectBox。GreenDao官网介绍中最前面有这么一句:
Note: for new apps we recommend ObjectBox, a new object-oriented database that is much faster than SQLite and easier to use.
对于新的应用程序,我们建议使用ObjectBox,这是一个新的面向对象的数据库,它比SQLite更快更方便使用。
显然是在极力推荐使用ObjectBox。所以花了点时间学习了一下,还不知道的同学们可一一起来了解..这一篇教你如何使用。当然官网也写的很详细,这里作者简单的做一个总结。
二、简介
Github:https://github.com/objectbox/objectbox-java
官网对ObjectBox的介绍:
ObjectBox is a super fast database and sychronization solution, built uniquely for Mobile and IoT devices. We bring edge computing to small devices, allowing data to be stored and processed from sensor to server for reliable, fast and secure data management. ObjectBox is smaller than 1MB, so it is the ideal solution across hardware from Mobile Apps, to IoT Devices and IoT Gateways. We are the first high-performance NoSQL, ACID-compliant on-device edge database. All of our products are built with developers in mind, so they are easy to use and take minimal code to implement.
个人勉强可以看懂英文这里就不献丑,只好把原文搬过来。https://objectbox.io/ 想要了解更多官网走一波。
总结起来就是:速度快 占用小 使用方便 .... 感觉这就够了 。不正是我们所需要的那样么
好了,废话就不多说了 。作者向您丢了一坨代码、、、
三、实现步骤
(1)项目引用ObjectBox
根目录build.gradle
buildscript {
ext.objectboxVersion = '2.3.4'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion"
}
}
App build.gradle
apply plugin: 'com.android.application'
apply plugin: 'io.objectbox' // apply last
(2)建立实体类
// User.java
@Entity
public class User {
//实体必须具有一个类型的long 类型的Id属性 如若需要使用其它类型的Id 请查看文档
@Id public long id;
public String name;
}
建立后 :Build> Make project
这会触发ObjectBox生成一些类,比如ObjectBox内部使用的一些类。 MyObjectBox.java
注意:如果您对实体进行了重大更改,例如通过移动它们或修改注释,请确保重建项目,以便更新生成的ObjectBox代码。
核心类:
- MyObjectBox:基于实体类生成,MyObjectBox提供了一个构建器,用于为您的应用程序设置BoxStore。
- BoxStore:入口点使用ObjectBox。BoxStore是您与数据库的直接接口并管理Boxes。
- Box:一个Box保存并查询实体。对于每个实体,都有一个Box(由BoxStore提供)
(3)开始使用
步骤1:获取BoxStore
BoxStore boxStore = MyObjectBox.builder().androidContext(context.getApplicationContext()).build();
步骤2:通过BoxStore ,获取Box
Box<User> userBox = boxStore.boxFor(User.class);
步骤3:通过Box提供的方法对数据进行增删改查操作
//Box常用函数 更多请查看API文档
count():返回Box中存储对象的数量
get():获取存储对象
getAll():获取所有存储对象
isEmpty():判断Box中是否有对象
put():存储与更新对象
query():查询数据
remove():删除指定数据
removeAll():删除所有数据
四、额外扩展
(1)使用ObjectBox帮助类来配置BoxStore
/**
* 在Application类onCreate()方法中调用:ObjectBox.init(this);
* 可以在ObjectBox帮助类中初始化BoxStore
*/
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; }
}
Box<User> userBox = ObjectBox.get().boxFor(User.class);
(2)注释说明
- @Entity:ObjectBox只保存用此注释标记的类的对象
- @Id:实体必须有一个long类型的Id属性,这样能有效的获取或引用对象
- @NameInDb:如果名称在Java端出现分歧(相对于DB),可以在这里指定数据库中使用的名称。允许在Java中进行简单的重命名。
- @Transient:表示该字段不会持久存储在数据库中
- @Index:指定该属性为索引,如果使用该属性进行查询。查询该属性时,可以提高性能。
- @Unique:将属性值标记为唯一
- @Backlink:定义反向链接关系,该关系基于另一个反向关系
- @BaseEntity:实体基类的注释。
- @NotNull:指定该属性不为空
- @TargetIdProperty:定义作为ToOne的目标ID的属性。
(3)查询
官网摘录:
1.查询名 Joe的所有用户
List<User> joes = userBox.query().equal(User_.firstName, "Joe").build().find();
2.多个条件示例:获取名字为“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();
3.排序
userBox.query().equal(User_.firstName, "Joe")
.order(User_.lastName, QueryBuilder.DESCENDING | QueryBuilder.CASE_SENSITIVE)
.find();
4.限制,偏移和分页
Query<User> query = userBox.query().equal(UserProperties.FirstName, "Joe").build();
List<User> joes = query.find(/* offset by */ 10, /* limit to */ 5 /* results */);
5.如果您只想返回某个属性的值而不是完整对象列表,则可以使用PropertyQuery
String[] emails = userBox.query().build().property(User_.email).findStrings();
6.处理空值:默认情况下,不返回空值。但是,如果属性为null,则可以指定要返回的替换值
String[] emails = userBox.query().build()
.property(User_.email)
.nullValue("unknown")
.findStrings();
7.返回值去重
String[] names = userBox.query().build()
.property(User_.firstName)
.distinct()
.findStrings();
8.默认情况下,将忽略字符串的大小写。但是,可以重载distinct调用以启用区分大小写:
String[] names = userBox.query().build()
.property(User_.firstName)
.distinct(StringOrder.CASE_SENSITIVE)
.findStrings();
9.聚合值
min()/ :在与查询匹配的所有对象上查找给定属性的最小值。minDouble()
max()/ :找到最大值。maxDouble()
sum()/ :计算所有值的总和。注意:非double版本检测溢出并在这种情况下抛出异常。sumDouble()
avg() :计算所有值的平均值(总是两倍)。
count():返回结果数。这比查找和获取结果数组的长度更快。可以结合使用,仅计算不同值的数量。自2.0.0起distinct()
10.查询过滤器
// Reduce object count to reasonable value
songBox.query().equal(Song_.bandId, bandId)
// Filter is performed on candidate objects
.filter((song) -> {
return song.starCount * 2 > song.downloads;
})
(4)Data Observers & Rx
简单理解:ObjectBox提供了Observer关联,可以使数据库操作在子线程进行,在主线程中及时进行UI更新。
具体可以查看官网 ,下面是个人写的一个Demo。大家可以参考参考
import java.util.List;
import io.objectbox.Box;
import io.objectbox.android.AndroidScheduler;
import io.objectbox.query.Query;
import io.objectbox.reactive.DataObserver;
import io.objectbox.reactive.DataSubscriptionList;
import io.objectbox.reactive.DataTransformer;
import io.objectbox.reactive.ErrorObserver;
/**
* ObjectBox
*/
public class LinQuery<T> {
private DataSubscriptionList subscriptions = new DataSubscriptionList();
public Box getBox(Class<T> object){
Box<T> tBox = ObjectBox.get().boxFor(object);
return tBox;
}
public void subscribes(Query<T> query,DataTransformer datas,ErrorObserver error,DataObserver success) {
query.subscribe(subscriptions).on(AndroidScheduler.mainThread()).transform(datas).onError(error).observer(success);
}
/**
* 取消订阅
*/
public void cancelSubscribe() {
subscriptions.cancel();
}
/**
* 转换数据
*/
DataTransformer datas = new DataTransformer<List<T>, Object>() {
@Override
public Object transform(List<T> source) throws Exception {
return null;
}
};
/**
* 错误返回
*/
ErrorObserver error = new ErrorObserver() {
@Override
public void onError(Throwable th) {
}
};
/**
* 成功返回
*/
DataObserver success = new DataObserver<T>() {
@Override
public void onData(T data) {
}
};
}
五、练习项目
实践是检验真理的唯一标准
学习了之后,当然要练习一下,如果跟看书似的的过一遍又会很快忘记。所以写了个Demo,加深印象还是很有必要的。
效果预览:
主要是根据一对一、一对多、多对多等关系来进行数据库的一些简单操作。
这里简单的贴部分单一存储操作代码、想了解更多的可以去项目里面查看
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_add://增
User user1 = new User();
user1.setName("xx" + i++);
userBox.put(user1);
query();
break;
case R.id.btn_delete://删
List<User> users1 = userBox.query().build().find();
int v2 = (int)(Math.random() * (users1.size()));
userBox.remove( users1.get(v2));
query();
break;
case R.id.btn_update://改
List<User> users = userBox.query().build().find();
if(users.size()==0) return;
int v1 = (int)(Math.random() * (users.size()));
User user = users.get(v1);
if(user.getName().contains("xx")){
user.setName("oo"+v1);
}else{
user.setName("xx"+v1);
}
userBox.put(user);
query();
break;
case R.id.btn_query://查
query();
break;
}
}
private void query() {
List<User> all = userBox.getAll();
adapter.setData(all);
}
这里没有用订阅、作者比较懒就没写了。 如果在项目中可以考虑查询的时候用observer。
六、Demo地址
Github:https://github.com/DayorNight/ObjectBoxDemo
七、内容推荐
CSDN:
《Android 仿RxDialog自定义DialogFragment》
如果你觉得写的不错或者对您有所帮助的话
不妨顶一个【微笑】,别忘了点赞、收藏、加关注哈
看在花了这么多时间整理写成文章分享给大家的份上,记得手下留情哈
您的每个举动都是对我莫大的支持