Настройка ObjectBox базы данных в мобильном приложении
ObjectBox позиционирует себя как самую быструю embedded базу данных для мобильных устройств. Бенчмарки компании показывают 10x преимущество перед Room/SQLite на операциях записи. В реальности разрыв зависит от паттернов доступа, но ObjectBox действительно быстрее на массовых вставках объектов — за счёт нативного C++ движка без SQL-парсинга.
Когда ObjectBox имеет смысл
ObjectBox — объектная база, не реляционная. Нет JOIN, нет GROUP BY, нет агрегатных функций в привычном SQL-смысле. Если приложение работает с графом объектов (сущности со связями), а не с аналитическими запросами — ObjectBox выигрывает. Для IoT-приложений, трекеров, игровых сохранений, каталогов с фильтрацией — хорошо подходит.
Подключение и модели
// build.gradle (app)
plugins {
id("io.objectbox")
}
dependencies {
implementation("io.objectbox:objectbox-kotlin:3.8.0")
}
@Entity
data class Task(
@Id var id: Long = 0,
var title: String = "",
var description: String = "",
var priority: Int = 0,
var dueDate: Long = 0,
var isCompleted: Boolean = false
) {
// Связь ToMany настраивается через RelationInfo
val tags: ToMany<Tag> = toMany()
}
@Entity
data class Tag(
@Id var id: Long = 0,
var name: String = "",
@Index var color: String = ""
)
@Id — обязательный Long для внутреннего ObjectBox ID. Это не UUID и не ваш бизнес-идентификатор — используйте отдельное строковое поле для синхронизации с сервером.
Инициализация и BoxStore
// Application класс
class MyApp : Application() {
companion object {
lateinit var boxStore: BoxStore
private set
}
override fun onCreate() {
super.onCreate()
boxStore = MyObjectBox.builder()
.androidContext(this)
.name("tasks-db")
.build()
}
}
// Использование в ViewModel
class TaskViewModel : ViewModel() {
private val taskBox: Box<Task> = MyApp.boxStore.boxFor(Task::class.java)
val tasks: LiveData<List<Task>> = liveData(Dispatchers.IO) {
val query = taskBox.query(Task_.isCompleted.equal(false))
.order(Task_.priority, QueryBuilder.DESCENDING)
.build()
emitSource(query.subscribe().toLiveData())
}
}
query.subscribe().toLiveData() — ObjectBox DataObserver автоматически уведомляет при изменении данных в box. Это реактивная подписка без лишнего кода.
Запросы через QueryBuilder
ObjectBox не использует строковый SQL. Запросы через типобезопасный QueryBuilder с Properties — сгенерированными метаклассами (Task_, Tag_):
// Фильтрация с несколькими условиями
val urgentTasks = taskBox.query(
Task_.isCompleted.equal(false)
.and(Task_.priority.greater(2))
.and(Task_.dueDate.less(System.currentTimeMillis() + 86_400_000L))
)
.order(Task_.dueDate)
.build()
.find()
// Полнотекстовый поиск — требует @Index(type = IndexType.VALUE) + FTS
val searchResults = taskBox.query(
Task_.title.contains("meeting", StringOrder.CASE_INSENSITIVE)
)
.build()
.find()
Нет JOIN — отношения через ToOne/ToMany. ObjectBox подгружает связанные объекты lazy по умолчанию:
// ToMany загружается при первом обращении
val taskTags = task.tags // lazy load, обращение к DB
ObjectBox Sync
Как и Realm, ObjectBox предлагает коммерческий сервер синхронизации — ObjectBox Sync. Двусторонняя синхронизация, конфликт-резолюция, дельта-обновления. Это отдельный продукт с лицензионной моделью.
Типичные проблемы
ID не UUID. ObjectBox назначает Long ID автоматически — они уникальны только локально. Для серверной синхронизации нужен отдельный UUID-поле с @Index.
Codegen при каждой сборке. Плагин генерирует MyObjectBox.java и классы _. Если схема поменялась, а gradle cache не сбросился — компилятор жалуется на несоответствие. ./gradlew clean решает.
Открытый BoxStore — один на приложение. Попытка открыть второй BoxStore на тот же файл — исключение. Singleton через Application класс обязателен.
Настройка ObjectBox, модели, реактивные запросы для Android: 3–5 дней. Стоимость рассчитывается индивидуально.







