一口糕、前言:
以前開發(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 囚戚,如下圖:
從圖上可以看出除了在加載 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、刪除
/**
* 刪除數(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ù)庫的位置
6虾啦、查看數(shù)據(jù)庫里的數(shù)據(jù)
MyApplication.boxStore?.startObjectBrowser()