ObjectBox 最詳細的使用指南

一口糕、前言:

ObjectBox 官網(wǎng):
git地址點擊:

以前開發(fā)項目的時候 ORM 一直用的是 GreenDao ,這次新開項目的時候訪問 GreenDao 的官網(wǎng)的時候卻發(fā)現(xiàn)了一行新的 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超棺,這是一種新的面向對象數(shù)據(jù)庫霍衫,它比SQLite快得多,也更容易使用拜效。對于基于greenDAO的現(xiàn)有應用程序望抽,我們提供了DaoCompat,以便輕松切換(另請參閱公告)裕循。

瞅一眼官網(wǎng)簡介: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 囚戚,如下圖:

圖片.png

從圖上可以看出除了在加載 100k 的大量數(shù)據(jù)的時候 ObjectBox 的速度慢于 Realm浆竭,在執(zhí)行其他數(shù)據(jù)操作的時候 ObjectBox 的性能對其他兩位都是近乎碾壓式的存在站宗。

在引入后對 apk 包的大小影響方面,ObjectBox 和 Realm 分別在 1-1.5MB 和 3-4MB 财喳,Room 因為是對 SQLite 的封裝,只有 50KB 左右。而在增加的方法數(shù)量方面,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 數(shù)據(jù)庫缓溅,能夠快速地存儲和檢索數(shù)據(jù)喇勋。
  • 易于使用:ObjectBox 提供了簡單易用的 API,使得開發(fā)人員可以輕松地將其集成到應用程序中溯壶。
  • 跨平臺:ObjectBox 支持多種平臺,包括 Android、iOS募谎、Linux币绩、Windows 和 macOS截珍。
  • 數(shù)據(jù)模型靈活:ObjectBox 具有靈活的數(shù)據(jù)模型,可以輕松地適應不同的數(shù)據(jù)結構和需求箩朴。
  • 數(shù)據(jù)同步:ObjectBox 支持數(shù)據(jù)同步笛臣,可以在多個設備之間同步數(shù)據(jù)。
  • 數(shù)據(jù)安全:ObjectBox 提供了數(shù)據(jù)加密和身份驗證等安全功能隧饼,保護數(shù)據(jù)的安全性沈堡。
  • 高可靠性:ObjectBox 具有高可靠性,能夠保證數(shù)據(jù)的完整性和可靠性燕雁。

2诞丽、greenDao鲸拥、room和objectBox對比

greenDao、room和objectBox都是Android平臺上的ORM(對象關系映射)框架僧免,用于簡化應用程序與數(shù)據(jù)庫之間的交互刑赶。它們都有各自的優(yōu)點和適用場景。

  • greenDao是一個輕量級的ORM框架懂衩,它的主要特點是速度快颓哮、內存占用小驾凶、易于使用买雾。它使用代碼生成器來生成DAO(數(shù)據(jù)訪問對象)類犁跪,這些類可以直接訪問數(shù)據(jù)庫,從而避免了手動編寫SQL語句的繁瑣過程法希。greenDao支持多線程操作和事務處理枷餐,可以在高并發(fā)的情況下保證數(shù)據(jù)的一致性。它還提供了一些高級功能苫亦,如緩存毛肋、查詢優(yōu)化等。
  • room是Google官方推出的ORM框架屋剑,它是基于SQLite數(shù)據(jù)庫的润匙,可以與SQLite API無縫集成。room使用注解來定義實體類和DAO接口唉匾,可以自動生成數(shù)據(jù)庫表和DAO實現(xiàn)類孕讳。它支持類型安全的查詢、事務處理肄鸽、觀察者模式等功能卫病。room還提供了LiveData和ViewModel等組件油啤,可以方便地實現(xiàn)數(shù)據(jù)的觀察和管理典徘。
  • objectBox是一個高性能的ORM框架,它使用了一些新的技術來提高數(shù)據(jù)訪問的效率益咬。objectBox使用基于內存的數(shù)據(jù)結構來存儲數(shù)據(jù)逮诲,可以快速地進行查詢和更新操作。它還支持多線程操作和事務處理幽告,可以在高并發(fā)的情況下保證數(shù)據(jù)的一致性梅鹦。objectBox還提供了一些高級功能,如索引冗锁、關系映射齐唆、查詢優(yōu)化等。

總的來說冻河,greenDao適合對性能要求較高的應用程序箍邮,room適合與Android架構組件一起使用的應用程序茉帅,objectBox適合需要高性能和高可擴展性的應用程序。選擇哪個ORM框架取決于具體的應用場景和需求锭弊。

二堪澎、ObjectBox 常見的問題:

1、找不到MyObjectBox類

答:初次引入ObjectBox的時候味滞,在使用MyObjectBox類之前樱蛤,需要先完成一次編譯,然后再創(chuàng)建數(shù)據(jù)bean對象剑鞍,最后ObjectBox生成MyObjectBox類以后才能使用昨凡。

2、ObjectBox編譯無法產(chǎn)生MyObjectBox類

1攒暇、目前(objectbox 2.2.0)還不支持在數(shù)據(jù)庫bean里面添加集合屬性土匀,比如,List<String>,List<Object>等形用。針對此類情況就轧,可以

1.1.對于集合元素為基礎數(shù)據(jù)類型的屬性,例如List<String>田度,可以轉換為一個Json字符串存儲妒御,將集合屬性轉變?yōu)镾tring類型;
1.2.使用ObjectBox提供的ToMany類創(chuàng)建關聯(lián)關系镇饺。

2乎莉、在數(shù)據(jù)庫bean里面添加非基礎數(shù)據(jù)類型的數(shù)據(jù),需要使用ObjectBox提供的ToOne或者ToMany類進行包裝奸笤,否則無法生成MyObjectBox類惋啃。

3、數(shù)據(jù)庫bean中的屬性一定是 Pubilc

數(shù)據(jù)庫bean的屬性如果是private监右,會無法編譯完成边灭。只能設置為public。

4健盒、保持objectbox-models/default.json唯一

default.json中保存的是Objectbox數(shù)據(jù)庫所有現(xiàn)存字段的id值绒瘦,對于Objectbox管理數(shù)據(jù)庫而言非常重要。在合作開發(fā)中扣癣,多個人的編譯結果最好以其中一人的為準惰帽。否則數(shù)據(jù)庫不能正常使用。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/DialogDataBase

使用時特別注意:

1该酗、類上面可以打@Entity,如果是基類則打@BaseEntity士嚎。
2呜魄、一定要有一個@Id烁焙,類型為Long的屬性,用于自增屬性(也可以指定值用@Id(assignable = true))耕赘。
3骄蝇、kotlin中的data class一定要有默認值,不然可能會找不到默認的構造方法操骡。
4九火、如果某個字段不想序列化到數(shù)據(jù)庫中可以打上:@Transient標簽,從kotlin里或者objectBox中導入的都可以册招。

注意: 在使用ObjectBox插入超過1500條數(shù)據(jù)的時候岔激,插入的順序和存儲的順序不一致,for循環(huán)插入也不行(1000條數(shù)據(jù)插入后是掰,休眠3秒再插入也不行)虑鼎,我們可以在查詢的時候,按照一定的順序排列查出键痛。

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對象之前一定要先創(chuàng)建一個實體,否則MyObjectBox找不到丁频。

1杉允、首先構建一個User對象

@Entity
class User {
    //assignable= true可以手動指定id值,出現(xiàn)相同會替換席里;不寫這個給id賦值會報錯
    @Id(assignable = true)
    var id: Long = 0
    var name: String = ""
    var sex: Long = 0
    var desc: String = ""
}

第一次put數(shù)據(jù)時報錯信息:ID is higher or equal to internal ID sequence: 12345 (vs. 1). Use ID 0 (zero).

@Id(assignable = true)是指在使用BoxStore的put方法時叔磷,允許將已經(jīng)存在的對象的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

        //數(shù)據(jù)庫
        var boxStore: BoxStore? = null
    }

    override fun onCreate() {
        super.onCreate()
        appContext = this

        initObjectBox()
    }

    /**
     * 初始化數(shù)據(jù)庫
     */
    private fun initObjectBox() {
        //MyObjectBox找不到案疲,必須先創(chuàng)建一個對象,然后重新編譯麻养,才可以
        boxStore = MyObjectBox.builder().androidContext(this).build()
    }
}

3褐啡、數(shù)據(jù)更新。

注意:更新數(shù)據(jù)(如果直接插入更新的對象(所有的字段都會被替換掉)鳖昌,有些字段沒有值會覆蓋掉)

1备畦、先查詢到數(shù)據(jù)
2低飒、對查詢到的數(shù)據(jù)字段進行更新
3、查詢不到懂盐,直接插入

1褥赊、插入數(shù)據(jù)

// 插入數(shù)據(jù)
   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","插入數(shù)據(jù)1:${result}")
                queryAllData()
            }

2、更新數(shù)據(jù)

// 更新數(shù)據(jù)
  btnUpdate?.setOnClickListener {
                var user = User()
                user.id = 123L
                user.desc = "更改后的表述"
                var result =  ObjectBoxUtils.addData(user,User::class.java)
                Log.d("lyy","更改數(shù)據(jù):${result}")
                queryAllData()
            }

3莉恼、打印結果:

com.sht.myapplication1               D  插入數(shù)據(jù)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  更改數(shù)據(jù):123
com.sht.myapplication1               D  id: 111  name: 小剛  sex: 8  desc: 
com.sht.myapplication1               D  id: 123  name:   sex: 0  desc: 更改后的表述

總結:因為插入數(shù)據(jù)和更新數(shù)據(jù)是同一個put()方法拌喉,如果你new User()類,只給desc 賦值俐银,其它字段(name和sex的值就會為空)尿背,所以,我們應該先查到對象捶惜,然后更新查到對象的一個字段田藐。

推薦例子:

  /**
     * 更新數(shù)據(jù)(如果直接插入更新的對象,有些字段沒有值會覆蓋掉)
     * 1吱七、先查詢到數(shù)據(jù)
     * 2汽久、對查詢到的數(shù)據(jù)字段進行更新
     * 3、查詢不到踊餐,直接插入
     */
    fun updateData(o: User, c: Class<User>) {
        try {
            val boxStore: BoxStore? = init()
            if (boxStore != null && !boxStore.isClosed) {
                //1回窘、先查詢到數(shù)據(jù)
                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、對查詢到的數(shù)據(jù)字段進行更新
                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

/***
 * 數(shù)據(jù)庫封裝
 */
object ObjectBoxUtils {

    /**
     * 初始化數(shù)據(jù)庫
     */
    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
    }

    /**
     * 重啟數(shù)據(jù)庫
     * 刪除本地數(shù)據(jù)庫后苍碟,需要重新創(chuàng)建
     */
    fun  restartBoxStore(){
         boxStore = MyObjectBox.builder().androidContext(MyApplication.appContext).build()
        MyApplication.boxStore = boxStore
    }

    /**
     * 添加數(shù)據(jù)
     */
    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
    }

    /**
     * 更新數(shù)據(jù)(如果直接插入更新的對象酒觅,有些字段沒有值會覆蓋掉)
     * 1、先查詢到數(shù)據(jù)
     * 2微峰、對查詢到的數(shù)據(jù)字段進行更新
     * 3舷丹、查詢不到,直接插入
     */
    fun updateData(o: User, c: Class<User>) {
        try {
            val boxStore: BoxStore? = init()
            if (boxStore != null && !boxStore.isClosed) {
                //1蜓肆、先查詢到數(shù)據(jù)
                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颜凯、對查詢到的數(shù)據(jù)字段進行更新
                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()}")
        }

    }


    /**
     * 添加數(shù)組
     */
    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")
        }
    }

    /**
     * 獲取全部對象數(shù)據(jù)
     */
    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>()
    }

    /**
     * 查詢單個數(shù)據(jù)
     */
    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
    }

    /**
     * 刪除數(shù)據(jù)單個數(shù)據(jù)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
    }


    /**
     * 刪除數(shù)據(jù)單個數(shù)據(jù)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) {
        }
    }

    /**
     * 刪除列表數(shù)據(jù)
     */
    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;

/**
 * 書籍數(shù)據(jù)庫管理類
 */
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;
    }

    /**
     * 添加數(shù)據(jù)
     */
    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<>();
    }

    //刪除數(shù)據(jù)
    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) {
        }
    }

    //刪除數(shù)據(jù)
    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;
    }

    //刪除數(shù)據(jù)
    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;
    }

    /**
     * 刪除數(shù)據(jù)
     */
    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;
    }

    /**
     * 獲取指定章節(jié)書簽全部列表
     * @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","插入數(shù)據(jù)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","插入數(shù)據(jù)2:${result}")
                queryAllData()
            }
            btnDelete1?.setOnClickListener {
                var id = 123L
                var result =  ObjectBoxUtils.deleteUserData(id)
                Log.d("lyy","刪除數(shù)據(jù)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","更改數(shù)據(jù):${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、刪除

圖片.png
 /**
     * 刪除數(shù)據(jù)單個數(shù)據(jù)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
    }


    /**
     * 刪除數(shù)據(jù)單個數(shù)據(jù)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) {
        }
    }

    /**
     * 刪除列表數(shù)據(jù)
     */
    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

  /**
     * 獲取全部對象數(shù)據(jù)
     */
    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>()
    }

    /**
     * 查詢單個數(shù)據(jù)
     */
    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
    }

 //查詢列表數(shù)據(jù)募壕,按照一定順序排列query().order(BookChapter_.display_order)
  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().order(BookChapter_.display_order)
                        .equal(BookChapter_.book_id, book_id)
                        .equal(BookChapter_.user_id, NewChapterManageUtils.INSTANCE.getUIDToLong())
                        .build().find();
                return joes;
            }
        } catch (Exception e) {
        }
        return new ArrayList<>();
    }
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调炬、清空數(shù)據(jù)庫數(shù)據(jù)

1、方式1:

//是清除了表格中的所有數(shù)據(jù)舱馅,數(shù)據(jù)表和結構都在缰泡,不需要重啟
MyApplication.boxStore?.removeAllObjects()

2、方式2(必須重啟才能繼續(xù)使用數(shù)據(jù)庫):
和方法3一樣

    //先關閉了數(shù)據(jù)庫代嗤,然后清除(無法進行操作了)
      MyApplication.boxStore?.close()
      //這個方法只會刪除存儲在 Box 中的所有文件匀谣。
      MyApplication.boxStore?.deleteAllFiles()
     //重啟數(shù)據(jù)庫
      ObjectBoxUtils. restartBoxStore()

它會刪除所有與該數(shù)據(jù)庫相關的文件,包括數(shù)據(jù)文件资溃、索引文件武翎、鎖文件等。

3溶锭、方式3(必須重啟才能繼續(xù)使用數(shù)據(jù)庫):

//先關閉了數(shù)據(jù)庫宝恶,然后清除(無法進行操作了)
MyApplication.boxStore?.close()
//清除這個數(shù)據(jù)庫,重新創(chuàng)建
MyApplication.boxStore?.deleteAllFiles()
//重啟數(shù)據(jù)庫
ObjectBoxUtils. restartBoxStore()

objectBox中的deleteAllFiles()方法是用于刪除所有數(shù)據(jù)庫文件的方法趴捅。它會刪除所有與該數(shù)據(jù)庫相關的文件垫毙,包括數(shù)據(jù)文件、索引文件拱绑、鎖文件等综芥。這個方法通常用于清空整個數(shù)據(jù)庫,或者在重新創(chuàng)建數(shù)據(jù)庫時使用猎拨。需要注意的是膀藐,使用該方法會永久刪除所有數(shù)據(jù),因此在使用前需要謹慎考慮红省。

4额各、方式4(重啟數(shù)據(jù)庫)

    /**
     * 重啟數(shù)據(jù)庫
     * 刪除本地數(shù)據(jù)庫后,需要重新創(chuàng)建
     */
    fun  restartBoxStore(){
         boxStore = MyObjectBox.builder().androidContext(MyApplication.appContext).build()
         MyApplication.boxStore = boxStore
    }

5吧恃、數(shù)據(jù)庫的位置

圖片.png

6虾啦、查看數(shù)據(jù)庫里的數(shù)據(jù)

MyApplication.boxStore?.startObjectBrowser()

查看方式1:
查看方式2:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市痕寓,隨后出現(xiàn)的幾起案子傲醉,更是在濱河造成了極大的恐慌,老刑警劉巖呻率,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件硬毕,死亡現(xiàn)場離奇詭異,居然都是意外死亡筷凤,警方通過查閱死者的電腦和手機昭殉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來藐守,“玉大人挪丢,你說我怎么就攤上這事÷В” “怎么了乾蓬?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長慎恒。 經(jīng)常有香客問我任内,道長,這世上最難降的妖魔是什么融柬? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任死嗦,我火速辦了婚禮,結果婚禮上粒氧,老公的妹妹穿的比我還像新娘越除。我一直安慰自己,他們只是感情好外盯,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布摘盆。 她就那樣靜靜地躺著,像睡著了一般饱苟。 火紅的嫁衣襯著肌膚如雪孩擂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天箱熬,我揣著相機與錄音类垦,去河邊找鬼。 笑死城须,一個胖子當著我的面吹牛护锤,可吹牛的內容都是我干的。 我是一名探鬼主播酿傍,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼烙懦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赤炒?” 一聲冷哼從身側響起氯析,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎莺褒,沒想到半個月后掩缓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡遵岩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年你辣,在試婚紗的時候發(fā)現(xiàn)自己被綠了巡通。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡舍哄,死狀恐怖宴凉,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情表悬,我是刑警寧澤弥锄,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站蟆沫,受9級特大地震影響籽暇,放射性物質發(fā)生泄漏。R本人自食惡果不足惜饭庞,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一戒悠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧舟山,春花似錦救崔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至幅骄,卻和暖如春劫窒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拆座。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工主巍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挪凑。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓孕索,卻偏偏與公主長得像,于是被迫代替她去往敵國和親躏碳。 傳聞我的和親對象是個殘疾皇子搞旭,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內容