一、前言:
以前开发项目的时候 ORM 一直用的是 GreenDao ,这次新开项目的时候访问 GreenDao 的官网的时候却发现了一行新的 Note: for new apps we recommend ObjectBox, a new object-oriented database that is much faster than SQLite and easier to use. For existing apps based on greenDAO we offer DaoCompat for an easy switch (see also the announcement).
翻译:注意:对于新的应用程序,我们推荐ObjectBox,这是一种新的面向对象数据库,它比SQLite快得多,也更容易使用。对于基于greenDAO的现有应用程序,我们提供了DaoCompat,以便轻松切换(另请参阅公告)。
瞅一眼官网简介:ObjectBox is a super fast mobile database that persists objects. It lets you avoid many repetitive tasks and offers a simple interface to your data. 翻译一下就是:更快,更简单。翻了一下 FAQ,对比了一下 ObjectBox 和 谷歌两位亲儿子 Realm 和 Room ,如下图:
![](https://img.haomeiwen.com/i11268516/d88b926dbdf4c32f.png)
从图上可以看出除了在加载 100k 的大量数据的时候 ObjectBox 的速度慢于 Realm,在执行其他数据操作的时候 ObjectBox 的性能对其他两位都是近乎碾压式的存在。
在引入后对 apk 包的大小影响方面,ObjectBox 和 Realm 分别在 1-1.5MB 和 3-4MB ,Room 因为是对 SQLite 的封装,只有 50KB 左右。而在增加的方法数量方面,Room 的 300 个方法也远少于 Room 的 2000 个方法和 ObjectBox 的 1300 个方法。关于三者的对比,可以看这篇文章:https://notes.devlabs.bg/realm-objectbox-or-room-which-one-is-for-you-3a552234fd6e
注意:如果不考虑对包的体积大小的影响,只考虑性能的话,似乎就有了选择 ObjectBox 的理由。
1、ObjectBox的特点
高性能:
ObjectBox 是一个高性能的 NoSQL 数据库,能够快速地存储和检索数据。易于使用:
ObjectBox 提供了简单易用的 API,使得开发人员可以轻松地将其集成到应用程序中。跨平台:
ObjectBox 支持多种平台,包括 Android、iOS、Linux、Windows 和 macOS。数据模型灵活:
ObjectBox 具有灵活的数据模型,可以轻松地适应不同的数据结构和需求。数据同步:
ObjectBox 支持数据同步,可以在多个设备之间同步数据。数据安全:
ObjectBox 提供了数据加密和身份验证等安全功能,保护数据的安全性。高可靠性:
ObjectBox 具有高可靠性,能够保证数据的完整性和可靠性。
2、greenDao、room和objectBox对比
greenDao、room和objectBox
都是Android平台上的ORM(对象关系映射)框架
,用于简化应用程序与数据库之间的交互。它们都有各自的优点和适用场景。
greenDao
是一个轻量级的ORM框架,它的主要特点是速度快、内存占用小、易于使用。它使用代码生成器来生成DAO(数据访问对象)类,这些类可以直接访问数据库,从而避免了手动编写SQL语句的繁琐过程。greenDao支持多线程操作和事务处理,可以在高并发的情况下保证数据的一致性。它还提供了一些高级功能,如缓存、查询优化等。room
是Google官方推出的ORM框架,它是基于SQLite数据库的,可以与SQLite API无缝集成。room使用注解来定义实体类和DAO接口,可以自动生成数据库表和DAO实现类。它支持类型安全的查询、事务处理、观察者模式等功能。room还提供了LiveData和ViewModel等组件,可以方便地实现数据的观察和管理。objectBox
是一个高性能的ORM框架,它使用了一些新的技术来提高数据访问的效率。objectBox使用基于内存的数据结构来存储数据,可以快速地进行查询和更新操作。它还支持多线程操作和事务处理,可以在高并发的情况下保证数据的一致性。objectBox还提供了一些高级功能,如索引、关系映射、查询优化等。
总的来说,greenDao适合对性能要求较高的应用程序,room适合与Android架构组件一起使用的应用程序,objectBox适合需要高性能和高可扩展性的应用程序。选择哪个ORM框架取决于具体的应用场景和需求。
二、ObjectBox 常见的问题:
1、找不到MyObjectBox类
答:初次引入ObjectBox的时候,在使用MyObjectBox类之前,需要先完成一次编译,然后再创建数据bean对象,最后ObjectBox生成MyObjectBox类以后才能使用。
2、ObjectBox编译无法产生MyObjectBox类
1、目前(objectbox 2.2.0)还不支持在数据库bean里面添加集合属性,比如,List<String>,List<Object>等。针对此类情况,可以
1.1.对于集合元素为基础数据类型的属性,例如List<String>,可以转换为一个Json字符串存储,将集合属性转变为String类型;
1.2.使用ObjectBox提供的ToMany类创建关联关系。
2、在数据库bean里面添加非基础数据类型的数据,需要使用ObjectBox提供的ToOne或者ToMany类进行包装,否则无法生成MyObjectBox类。
3、数据库bean中的属性一定是 Pubilc
数据库bean的属性如果是private,会无法编译完成。只能设置为public。
4、保持objectbox-models/default.json唯一
default.json中保存的是Objectbox数据库所有现存字段的id值,对于Objectbox管理数据库而言非常重要。在合作开发中,多个人的编译结果最好以其中一人的为准。否则数据库不能正常使用。default.json原文是这样说的
default.json:
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
三、使用:
我自己写的demo:https://gitee.com/lyyon/DialogAndDatabase.git
使用时特别注意:
1、类上面可以打@Entity,如果是基类则打@BaseEntity。
2、一定要有一个@Id,类型为Long的属性,用于自增属性(也可以指定值用@Id(assignable = true))。
3、kotlin中的data class一定要有默认值,不然可能会找不到默认的构造方法。
4、如果某个字段不想序列化到数据库中可以打上:@Transient标签,从kotlin里或者objectBox中导入的都可以。
1、将ObjectBox Gradle插件添加到您的根目录中 build.gradle:
buildscript {
ext.objectboxVersion = "3.5.1"
repositories {
mavenCentral()
}
dependencies {
classpath("io.objectbox:objectbox-gradle-plugin:$objectboxVersion")
}
}
2、App的build.gradle添加
// Using plugins syntax:
plugins {
id("io.objectbox") // Add after other plugins.
}
// 将这句话放在末尾,不然会出问题
// Or using the old apply syntax:
apply plugin: "io.objectbox" // Add after other plugins.
3、Application的初始化
注意:在MyObjectBox对象之前一定要先创建一个实体,否则MyObjectBox找不到。
1、首先构建一个User对象
@Entity
class User {
//assignable= true可以手动指定id值,出现相同会替换;不写这个给id赋值会报错
@Id(assignable = true)
var id: Long = 0
var name: String = ""
var sex: Long = 0
var desc: String = ""
}
第一次put数据时报错信息:ID is higher or equal to internal ID sequence: 12345 (vs. 1). Use ID 0 (zero).
@Id(assignable = true)是指在使用BoxStore的put方法时,允许将已经存在的对象的id重新赋值。如果不加这个注解,则在put方法中尝试重新赋值id会抛出异常。
注意:操作完后,一定要重新编译,否则找不到MyObjectBox。
2、MyApplication 初始化
import android.app.Application
import android.content.Context
import com.sht.demo.bean.MyObjectBox
import io.objectbox.BoxStore
class MyApplication : Application() {
companion object {
//上下文
var appContext: Context? = null
//数据库
var boxStore: BoxStore? = null
}
override fun onCreate() {
super.onCreate()
appContext = this
initObjectBox()
}
/**
* 初始化数据库
*/
private fun initObjectBox() {
//MyObjectBox找不到,必须先创建一个对象,然后重新编译,才可以
boxStore = MyObjectBox.builder().androidContext(this).build()
}
}
3、数据更新。
注意:更新数据(如果直接插入更新的对象(所有的字段都会被替换掉),有些字段没有值会覆盖掉)
1、先查询到数据
2、对查询到的数据字段进行更新
3、查询不到,直接插入
1、插入数据
// 插入数据
btnAdd1.setOnClickListener {
var user = User()
user.id = 123L
user.name = "小明"
user.sex = 18
user.desc = "啊哈哈哈或或哈或或"
var result = ObjectBoxUtils.addData(user,User::class.java)
Log.d("lyy","插入数据1:${result}")
queryAllData()
}
2、更新数据
// 更新数据
btnUpdate?.setOnClickListener {
var user = User()
user.id = 123L
user.desc = "更改后的表述"
var result = ObjectBoxUtils.addData(user,User::class.java)
Log.d("lyy","更改数据:${result}")
queryAllData()
}
3、打印结果:
com.sht.myapplication1 D 插入数据1:123
com.sht.myapplication1 D id: 111 name: 小刚 sex: 8 desc:
com.sht.myapplication1 D id: 123 name: 小明 sex: 18 desc: 啊哈哈哈或或哈或或
com.sht.myapplication1 D 更改数据:123
com.sht.myapplication1 D id: 111 name: 小刚 sex: 8 desc:
com.sht.myapplication1 D id: 123 name: sex: 0 desc: 更改后的表述
总结:因为插入数据和更新数据是同一个put()方法,如果你new User()类,只给desc 赋值,其它字段(name和sex的值就会为空),所以,我们应该先查到对象,然后更新查到对象的一个字段。
推荐例子:
/**
* 更新数据(如果直接插入更新的对象,有些字段没有值会覆盖掉)
* 1、先查询到数据
* 2、对查询到的数据字段进行更新
* 3、查询不到,直接插入
*/
fun updateData(o: User, c: Class<User>) {
try {
val boxStore: BoxStore? = init()
if (boxStore != null && !boxStore.isClosed) {
//1、先查询到数据
val box: Box<User> = boxStore.boxFor(User::class.java)
val list: MutableList<User> = box.query().equal(User_.id, o.id).build().find()
var localBean = list.getOrNull(0)
//2、对查询到的数据字段进行更新
localBean?.let {
localBean.desc = o.desc
boxStore.boxFor<User>(c).put(localBean)
}?: kotlin.run {
//3、查询不到,直接插入
boxStore.boxFor<User>(c).put(o)
}
}
} catch (e: Throwable) {
Log.d("lyy", "error:${e.printStackTrace()}")
}
}
4、Kotlin 工具类封装
package com.sht.demo.tools
import android.util.Log
import com.sht.demo.MyApplication
import com.sht.demo.bean.MyObjectBox
import com.sht.demo.bean.User
import com.sht.demo.bean.User_
import io.objectbox.Box
import io.objectbox.BoxStore
/***
* 数据库封装
*/
object ObjectBoxUtils {
/**
* 初始化数据库
*/
var boxStore: BoxStore? = null
fun init(): BoxStore? {
try {
boxStore = MyApplication.boxStore
if (boxStore == null) {
boxStore =
MyObjectBox.builder().androidContext(MyApplication.appContext).build()
MyApplication.boxStore = boxStore
}
} catch (e: Exception) {
}
return boxStore
}
/**
* 重启数据库
* 删除本地数据库后,需要重新创建
*/
fun restartBoxStore(){
boxStore = MyObjectBox.builder().androidContext(MyApplication.appContext).build()
MyApplication.boxStore = boxStore
}
/**
* 添加数据
*/
fun <Any> addData(o: Any, c: Class<Any>): Long {
try {
val boxStore: BoxStore? = init()
if (boxStore != null && !boxStore.isClosed) {
return boxStore.boxFor<Any>(c).put(o)
}
} catch (e: Throwable) {
Log.d("lyy", "error:${e.printStackTrace()}")
}
return 0
}
/**
* 更新数据(如果直接插入更新的对象,有些字段没有值会覆盖掉)
* 1、先查询到数据
* 2、对查询到的数据字段进行更新
* 3、查询不到,直接插入
*/
fun updateData(o: User, c: Class<User>) {
try {
val boxStore: BoxStore? = init()
if (boxStore != null && !boxStore.isClosed) {
//1、先查询到数据
val box: Box<User> = boxStore.boxFor(User::class.java)
val list: MutableList<User> = box.query().equal(User_.id, o.id).build().find()
var localBean = list.getOrNull(0)
//2、对查询到的数据字段进行更新
localBean?.let {
localBean.desc = o.desc
boxStore.boxFor<User>(c).put(localBean)
}?: kotlin.run {
//3、查询不到,直接插入
boxStore.boxFor<User>(c).put(o)
}
}
} catch (e: Throwable) {
Log.d("lyy", "error:${e.printStackTrace()}")
}
}
/**
* 添加数组
*/
fun <T> addData(list: List<Any>?, c: Class<Any>?) {
try {
//MyToash.Log("home","---oo: "+oo.size());
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
boxStore.boxFor<Any>(c).put(list)
}
} catch (e: java.lang.Exception) {
Log.d("lyy", "---error:$e")
}
}
/**
* 获取全部对象数据
*/
fun <Any> getAllData(clazz: Class<Any>?): List<Any>? {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<Any> = boxStore.boxFor<Any>(clazz)
return box.all
}
} catch (e: java.lang.Exception) {
}
return ArrayList()
}
/**
* 条件查询
*/
fun getUserData(): List<User>? {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<User> = boxStore.boxFor(User::class.java)
return box.query().equal(User_.sex, 1).build().find()
}
} catch (e: java.lang.Exception) {
}
return ArrayList<User>()
}
/**
* 查询单个数据
*/
fun getUser(id: Long): User? {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<User> = boxStore.boxFor(User::class.java)
return box[id]
}
} catch (e: java.lang.Exception) {
}
return null
}
/**
* 删除数据单个数据1
*/
fun deleteUserData(id: Long): Boolean {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<User> = boxStore.boxFor(User::class.java)
return box.remove(id)
}
} catch (e: java.lang.Exception) {
}
return false
}
/**
* 删除数据单个数据2
*/
fun <Any> deleteData(o: Any, clazz: Class<Any>?) {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<Any> = boxStore.boxFor<Any>(clazz)
box.remove(o)
}
} catch (e: java.lang.Exception) {
}
}
/**
* 删除列表数据
*/
fun <T> deletALLeData(o: List<Any>?, clazz: Class<Any>?) {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<Any> = boxStore.boxFor<Any>(clazz)
box.remove(o)
}
} catch (e: java.lang.Exception) {
}
}
}
4、Java 工具类封装
import com.youjiakeji.yjkjreader.base.BWNApplication;
import com.youjiakeji.yjkjreader.model.Audio;
import com.youjiakeji.yjkjreader.model.AudioChapter;
import com.youjiakeji.yjkjreader.model.AudioChapter_;
import com.youjiakeji.yjkjreader.model.Audio_;
import com.youjiakeji.yjkjreader.model.Book;
import com.youjiakeji.yjkjreader.model.BookChapter;
import com.youjiakeji.yjkjreader.model.BookChapter_;
import com.youjiakeji.yjkjreader.model.BookMarkBean_;
import com.youjiakeji.yjkjreader.model.Book_;
import com.youjiakeji.yjkjreader.model.Comic;
import com.youjiakeji.yjkjreader.model.ComicChapter;
import com.youjiakeji.yjkjreader.model.ComicChapter_;
import com.youjiakeji.yjkjreader.model.Comic_;
import com.youjiakeji.yjkjreader.model.Downoption;
import com.youjiakeji.yjkjreader.model.Downoption_;
import com.youjiakeji.yjkjreader.model.BookMarkBean;
import com.youjiakeji.yjkjreader.model.MyObjectBox;
import com.youjiakeji.yjkjreader.ui.utils.MyToash;
import java.util.ArrayList;
import java.util.List;
import io.objectbox.Box;
import io.objectbox.BoxStore;
/**
* 书籍数据库管理类
*/
public class ObjectBoxUtils {
public static BoxStore init() {
BoxStore boxStore = null;
try {
boxStore = BWNApplication.applicationContext.getBoxStore();
if (boxStore == null) {
boxStore = MyObjectBox.builder().androidContext(BWNApplication.applicationContext).build();
BWNApplication.applicationContext.setBoxStore(boxStore);
}
} catch (Exception e) {
}
return boxStore;
}
/**
* 添加数据
*/
public static <T> long addData(T o, Class c) {
//MyToash.Log("home",c.getName());
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
return boxStore.boxFor(c).put(o);
}
} catch (Throwable e) {
}
return 0;
}
public static <T> void addData(List<T> oo, Class c) {
try {
//MyToash.Log("home","---oo: "+oo.size());
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
boxStore.boxFor(c).put(oo);
}
} catch (Exception e) {
MyToash.Log("lyy", "---error:"+e.toString());
}
}
public static <T> List<T> getAllData(Class clazz) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<T> box = boxStore.boxFor(clazz);
return box.getAll();
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<Book> getBookShelfData() {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Book> box = boxStore.boxFor(Book.class);
List<Book> joes = box.query().equal(Book_.is_collect, 1).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<Downoption> getDownoptionsfData(long book_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Downoption> box = boxStore.boxFor(Downoption.class);
List<Downoption> joes = box.query().equal(Downoption_.book_id, book_id).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<BookChapter> getBookChapterItemfData(long book_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookChapter> box = boxStore.boxFor(BookChapter.class);
List<BookChapter> joes = box.query().equal(BookChapter_.book_id, book_id).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<ComicChapter> getcomicDownOptionList(long comic_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<ComicChapter> box = boxStore.boxFor(ComicChapter.class);
List<ComicChapter> joes = box.query()
.equal(ComicChapter_.comic_id, comic_id)
.equal(ComicChapter_.downStatus, 1)
.build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<Comic> getyetDownComicList() {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Comic> box = boxStore.boxFor(Comic.class);
List<Comic> joes = box.query()
.notEqual(Comic_.down_chapters, 0)
.build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<ComicChapter> getComicChapterItemfData(long comic_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<ComicChapter> box = boxStore.boxFor(ComicChapter.class);
List<ComicChapter> joes = box.query().equal(ComicChapter_.comic_id, comic_id).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<AudioChapter> getAudioChapterItemfData(long audio_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<AudioChapter> box = boxStore.boxFor(AudioChapter.class);
List<AudioChapter> joes = box.query().equal(AudioChapter_.audio_id, audio_id).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static ComicChapter getComicChapter(long id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<ComicChapter> box = boxStore.boxFor(ComicChapter.class);
return box.get(id);
}
} catch (Exception e) {
}
return null;
}
public static Book getBook(long id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Book> box = boxStore.boxFor(Book.class);
return box.get(id);
}
} catch (Exception e) {
}
return null;
}
public static BookChapter getBookChapter(long chapter_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookChapter> box = boxStore.boxFor(BookChapter.class);
return box.get(chapter_id);
}
} catch (Exception e) {
}
return null;
}
public static Comic getComic(long id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Comic> box = boxStore.boxFor(Comic.class);
return box.get(id);
}
} catch (Exception e) {
}
return null;
}
public static List<Comic> getComicShelfData() {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Comic> box = boxStore.boxFor(Comic.class);
List<Comic> joes = box.query().equal(Comic_.is_collect, 1).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<Audio> getAudioShelfData() {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Audio> box = boxStore.boxFor(Audio.class);
List<Audio> joes = box.query().equal(Audio_.is_collect, 1).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
//删除数据
public static <T> void deleteData(Object o, Class clazz) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<T> box = boxStore.boxFor(clazz);
box.remove((T) o);
}
} catch (Exception e) {
}
}
//删除数据
public static <T> void deletALLeData(List<T> o, Class clazz) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<T> box = boxStore.boxFor(clazz);
box.remove(o);
}
} catch (Exception e) {
}
}
public static Downoption getDownoption(long id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Downoption> box = boxStore.boxFor(Downoption.class);
Downoption joe = box.query().equal(Downoption_.id, id).build().findFirst();
return joe;
}
} catch (Exception e) {
}
return null;
}
//删除数据
public static void deleteDownoption(long id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Downoption> box = boxStore.boxFor(Downoption.class);
box.remove(id);
}
} catch (Exception e) {
}
/* try {
Downoption downoption = getDownoption(id);
deleteData(downoption, Downoption.class);
} catch (Exception e) {
}*/
}
public static List<BookChapter> getBookChapterData(long book_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookChapter> box = boxStore.boxFor(BookChapter.class);
List<BookChapter> joes = box.query().equal(BookChapter_.book_id, book_id).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static List<BookChapter> getBookChapterMoreChapter_id(long book_id, long Chapter_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookChapter> box = boxStore.boxFor(BookChapter.class);
List<BookChapter> joes = box.query().equal(BookChapter_.book_id, book_id).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static BookChapter getBookChapterFirstData(long book_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookChapter> box = boxStore.boxFor(BookChapter.class);
BookChapter joes = box.query().equal(BookChapter_.book_id, book_id).build().findFirst();
if (joes != null) {
return joes;
}
return joes;
}
} catch (Exception e) {
}
return null;
}
/**
* 删除数据
*/
public static <T> void removeAllData(Class clazz) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<T> box = boxStore.boxFor(clazz);
box.removeAll();
}
} catch (Exception e) {
}
}
public static void removeAllBookChapterData(long book_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookChapter> box = boxStore.boxFor(BookChapter.class);
box.remove(getBookChapterItemfData(book_id));
}
} catch (Exception w) {
}
}
public static void removeAllComicChapterData(long comic_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<ComicChapter> box = boxStore.boxFor(ComicChapter.class);
box.remove(getComicChapterItemfData(comic_id));
}
} catch (Exception e) {
}
}
public static void removeAllAudioChapterData(long audio_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<AudioChapter> box = boxStore.boxFor(AudioChapter.class);
box.remove(getAudioChapterItemfData(audio_id));
}
} catch (Exception e) {
}
}
public static Audio getAudio(long id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Audio> box = boxStore.boxFor(Audio.class);
return box.get(id);
}
} catch (Exception e) {
}
return null;
}
public static List<AudioChapter> getAudioChapterData(long audio_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<AudioChapter> box = boxStore.boxFor(AudioChapter.class);
List<AudioChapter> joes = box.query().equal(AudioChapter_.audio_id, audio_id).build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
public static AudioChapter getAudioChapter(long chapter_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<AudioChapter> box = boxStore.boxFor(AudioChapter.class);
return box.get(chapter_id);
}
} catch (Exception e) {
}
return null;
}
public static List<Audio> getyetDownAudioList() {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<Audio> box = boxStore.boxFor(Audio.class);
List<Audio> joes = box.query()
.notEqual(Audio_.down_chapters, 0)
.build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
/**
* 添加书签
*/
public static long addBookMarkBean(BookMarkBean bookMarkBean) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
return boxStore.boxFor(BookMarkBean.class).put(bookMarkBean);
}
} catch (Exception e) {
} catch (Error error) {
}
return 0;
}
/**
* @return 获取全部书签列表
*/
public static List<BookMarkBean> getBookMarkBeanList(long book_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookMarkBean> box = boxStore.boxFor(BookMarkBean.class);
List<BookMarkBean> joes = box.query()
.equal(BookMarkBean_.book_id, book_id)
.build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
/**
* @return 获取指定书签
*/
public static BookMarkBean getBookMarkBean(long BookMarkBean_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookMarkBean> box = boxStore.boxFor(BookMarkBean.class);
return box.get(BookMarkBean_id);
}
} catch (Exception e) {
}
return null;
}
/**
* 获取指定章节书签全部列表
* @param chapter_id
* @return
*/
public static List<BookMarkBean> getChapterBookMarkBeanList(long chapter_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookMarkBean> box = boxStore.boxFor(BookMarkBean.class);
List<BookMarkBean> joes = box.query()
.equal(BookMarkBean_.chapter_id, chapter_id)
.build().find();
return joes;
}
} catch (Exception e) {
}
return new ArrayList<>();
}
/**
* 删除书签
* @param mark_id
* @return
*/
public static boolean removeMarkBean(long mark_id) {
try {
BoxStore boxStore = init();
if (boxStore != null && !boxStore.isClosed()) {
Box<BookMarkBean> box = boxStore.boxFor(BookMarkBean.class);
return box.remove(mark_id);
}
} catch (Exception e) {
}
return false;
}
}
5、使用测试
class ObjectBoxActivity:AppCompatActivity() {
var binding:ActivityObjectBoxBinding?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView<ActivityObjectBoxBinding>(this, R.layout.activity_object_box)
binding?.apply {
btnAdd1.setOnClickListener {
var user = User()
user.id = 123L
user.name = "小明"
user.sex = 18
user.desc = "啊哈哈哈或或哈或或"
var result = ObjectBoxUtils.addData(user,User::class.java)
Log.d("lyy","插入数据1:${result}")
queryAllData()
}
btnAdd2.setOnClickListener {
var user = User()
user.id = 111L
user.name = "小刚"
user.sex = 8
var result = ObjectBoxUtils.addData(user,User::class.java)
Log.d("lyy","插入数据2:${result}")
queryAllData()
}
btnDelete1?.setOnClickListener {
var id = 123L
var result = ObjectBoxUtils.deleteUserData(id)
Log.d("lyy","删除数据1:${result}")
queryAllData()
}
btnDelete2?.setOnClickListener {
var user = User()
user.id = 123L
ObjectBoxUtils.deleteData(user,User::class.java)
queryAllData()
}
btnUpdate?.setOnClickListener {
var user = User()
user.id = 123L
user.name = "小明明"
user.desc = "更改后的表述"
user.sex = 10
var result = ObjectBoxUtils.addData(user,User::class.java)
Log.d("lyy","更改数据:${result}")
queryAllData()
}
btnQuerySingle?.setOnClickListener {
var id = 123L
var bean = ObjectBoxUtils.getUser(id)
Log.d("lyy","id: ${bean?.id} name: ${bean?.name} sex: ${bean?.sex}")
}
btnQueryAll?.setOnClickListener {
queryAllData()
}
}
}
fun queryAllData(){
var list = ObjectBoxUtils.getAllData(User::class.java)
list?.forEach {
Log.d("lyy","id: ${it.id} name: ${it.name} sex: ${it.sex} desc: ${it.desc}")
}
}
}
四、增删改查分析:
1、新增和更新(是同一个方法)
fun <Any> addData(o: Any, c: Class<Any>): Long {
try {
val boxStore: BoxStore? = init()
if (boxStore != null && !boxStore.isClosed) {
return boxStore.boxFor<Any>(c).put(o)
}
} catch (e: Throwable) {
Log.d("lyy", "error:${e.printStackTrace()}")
}
return 0
}
2、删除
![](https://img.haomeiwen.com/i11268516/6994f235426fc94a.png)
/**
* 删除数据单个数据1
*/
fun deleteUserData(id: Long): Boolean {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<User> = boxStore.boxFor(User::class.java)
return box.remove(id)
}
} catch (e: java.lang.Exception) {
}
return false
}
/**
* 删除数据单个数据2
*/
fun <Any> deleteData(o: Any, clazz: Class<Any>?) {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<Any> = boxStore.boxFor<Any>(clazz)
box.remove(o)
}
} catch (e: java.lang.Exception) {
}
}
/**
* 删除列表数据
*/
fun <T> deletALLeData(o: List<Any>?, clazz: Class<Any>?) {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<Any> = boxStore.boxFor<Any>(clazz)
box.remove(o)
}
} catch (e: java.lang.Exception) {
}
}
3、查询
query的参考文档:https://docs.objectbox.io/queries
/**
* 获取全部对象数据
*/
fun <Any> getAllData(clazz: Class<Any>?): List<Any>? {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<Any> = boxStore.boxFor<Any>(clazz)
return box.all
}
} catch (e: java.lang.Exception) {
}
return ArrayList()
}
/**
* 条件查询
*/
fun getUserData(): List<User>? {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<User> = boxStore.boxFor(User::class.java)
return box.query().equal(User_.sex, 1).build().find()
}
} catch (e: java.lang.Exception) {
}
return ArrayList<User>()
}
/**
* 查询单个数据
*/
fun getUser(id: Long): User? {
try {
val boxStore = init()
if (boxStore != null && !boxStore.isClosed) {
val box: Box<User> = boxStore.boxFor(User::class.java)
return box[id]
}
} catch (e: java.lang.Exception) {
}
return null
}
val query = userBox.query()
.equal(User_.firstName, "Joe")
.greater(User_.yearOfBirth, 1970)
.startsWith(User_.lastName, "O")
.build()
val youngJoes = query.find()
//query.close() // Or keep the query instance to re-use it
val query = userBox.query(User_.firstName.equal("Joe")).build()
val joes = query.find()
query.close()
// equal AND (less OR oneOf)
val query = box.query(
User_.firstName equal "Joe"
and (User_.age less 12
or (User_.stamp oneOf longArrayOf(1012))))
.order(User_.age)
.build()
4、清空数据库数据
1、方式1:
//是清除了表格中的所有数据,数据表和结构都在,不需要重启
MyApplication.boxStore?.removeAllObjects()
2、方式2(必须重启才能继续使用数据库):
和方法3一样
//先关闭了数据库,然后清除(无法进行操作了)
MyApplication.boxStore?.close()
//这个方法只会删除存储在 Box 中的所有文件。
MyApplication.boxStore?.deleteAllFiles()
//重启数据库
ObjectBoxUtils. restartBoxStore()
它会删除所有与该数据库相关的文件,包括数据文件、索引文件、锁文件等。
3、方式3(必须重启才能继续使用数据库):
//先关闭了数据库,然后清除(无法进行操作了)
MyApplication.boxStore?.close()
//清除这个数据库,重新创建
MyApplication.boxStore?.deleteAllFiles()
//重启数据库
ObjectBoxUtils. restartBoxStore()
objectBox中的deleteAllFiles()
方法是用于删除所有数据库文件的方法。它会删除所有与该数据库相关的文件,包括数据文件、索引文件、锁文件等。
这个方法通常用于清空整个数据库,或者在重新创建数据库时使用。需要注意的是,使用该方法会永久删除所有数据,因此在使用前需要谨慎考虑。
4、方式4(重启数据库)
/**
* 重启数据库
* 删除本地数据库后,需要重新创建
*/
fun restartBoxStore(){
boxStore = MyObjectBox.builder().androidContext(MyApplication.appContext).build()
MyApplication.boxStore = boxStore
}
5、数据库的位置
![](https://img.haomeiwen.com/i11268516/be3635738c73dfa3.png)
6、查看数据库里的数据
MyApplication.boxStore?.startObjectBrowser()
网友评论