ObjectBox: co to jest, NoSQL BD i praca z danymi

Autor: IT Sectr Opublikowano: 2026-03-13 Czas czytania: 9 min

ObjectBox to wysokowydajna baza danych NoSQL zoptymalizowana dla urządzeń mobilnych i brzegowych. W przeciwieństwie do SQLite, używa własnego formatu przechowywania opartego na płaskich plikach bez warstwy SQL. Według ObjectBox Benchmarks, 2024, ObjectBox wykonuje operacje wstawiania i odczytu 10–100 razy szybciej niż SQLite na urządzeniach Android, co czyni go najlepszym wyborem dla wymagających aplikacji mobilnych.

Najważniejsze

  • ObjectBox — NoSQL BD z płaskimi plikami, bez SQL i warstwy ORM
  • Wydajność — 10–100 razy szybszy niż SQLite przy operacjach zapisu i odczytu
  • Wieloplatformowość — Android, iOS, Linux, macOS, Windows i WebAssembly
  • Reaktywność — wbudowane Observable i Flow do śledzenia zmian
  • Łatwa integracja — generowanie kodu przez adnotacje, bez zapytań SQL

Czym jest ObjectBox?

ObjectBox — to in-memory baza danych NoSQL opracowana przez niemiecką firmę ObjectBox.io. W przeciwieństwie do tradycyjnych relacyjnych baz danych, ObjectBox przechowuje obiekty bezpośrednio w płaskich plikach, używając własnego formatu SLOT (Super Lightweight Object Tree). Eliminuje to narzut związany z ORM i parserem SQL. Format SLOT jest zoptymalizowany do pracy na urządzeniach z ograniczoną pamięcią: dane są defragmentowane automatycznie, a rozmiar bazy danych jest średnio 4–6 razy mniejszy niż w przypadku równoważnej bazy SQLite przy tej samej liczbie rekordów.

ObjectBox obsługuje wszystkie główne platformy mobilne: Android, iOS i Flutter. Dla Androida dostępne jest generowanie kodu przez ObjectBox Gradle Plugin, który przetwarza adnotowane encje i tworzy klasy Box do pracy z danymi. Dla Flutter używana jest natywna wtyczka z opakowaniem Dart. Oprócz platform mobilnych, ObjectBox działa na Linux, macOS, Windows i WebAssembly, co pozwala na ponowne wykorzystanie modelu danych między aplikacją mobilną a synchronizacją serwerową.

Według danych badania ObjectBox (2023), baza danych jest używana w ponad 5000 aplikacjach w Google Play, w tym w aplikacjach z publicznością przekraczającą 10 milionów użytkowników. Główne scenariusze: buforowanie danych, praca w trybie offline i przechowywanie szeregów czasowych (IoT). ObjectBox jest szczególnie popularny w aplikacjach do śledzenia zdrowia i fitnessu, gdzie wymagane jest szybkie zapisywanie odczytów czujników na urządzeniu bez stałego połączenia internetowego oraz do zbierania analityki z wielu urządzeń.

Historia i pozycjonowanie

ObjectBox pojawił się jako alternatywa dla Realm i SQLite na platformę Android. Pierwsza stabilna wersja została wydana w 2018 roku. Kluczowa różnica w stosunku do Realm — ObjectBox nie ma ograniczeń GPL (używa Apache 2.0) i obsługuje więcej platform: od urządzeń mobilnych po serwery na Linux.

Główne możliwości

ObjectBox zapewnia: automatyczne generowanie klas Box, wbudowane indeksy do szybkiego wyszukiwania, transakcje z obsługą wycofywania, reaktywne zapytania przez RxJava i Kotlin Flow, a także synchronizację między urządzeniami przez ObjectBox Sync (autorski protokół). W przeciwieństwie do Firebase Realtime Database, ObjectBox Sync działa w modelu peer-to-peer bez centralnego serwera, co zmniejsza opóźnienia i koszty infrastruktury.

Jak działa ObjectBox?

ObjectBox przechowuje dane we własnym binarnym formacie .mdb (ObjectBox Data File). Każda encja (Entity) jest mapowana na jeden plik, gdzie rekordy są przechowywane sekwencyjnie ze stałym przesunięciem. Pozwala to odczytywać i zapisywać poszczególne obiekty bez pełnego skanowania pliku.

Do pracy z ObjectBox nie jest potrzebny SQL: zapytania są budowane przez fluent-API w kodzie. Kompilator generuje pomocnicze klasy MyObjectBox i pudełka (Box), które hermetyzują wszystkie operacje CRUD. Model danych jest opisywany przez adnotacje @Entity, @Id, @Index i @Relation.

kotlin
// Podłączenie ObjectBox w Android
class App: Application() {
    lateinit var boxStore: BoxStore

    override fun onCreate() {
        super.onCreate()
        boxStore = MyObjectBox.builder()
            .androidContext(this)
            .build()
    }
}

ObjectBox vs SQLite: porównanie wydajności

Według oficjalnych benchmarków, ObjectBox znacznie przewyższa SQLite pod względem szybkości operacji, szczególnie przy wsadowym wstawianiu i masowym odczycie. SQLite pozostaje jednak standardem de facto dla aplikacji mobilnych ze względu na rozpowszechnienie i wbudowane wsparcie SQL.

OperacjaObjectBoxSQLiteRóżnica
Wstawianie (1000 rekordów)~5 ms~180 msx36 szybciej
Odczyt (1000 rekordów)~3 ms~70 msx23 szybciej
Aktualizacja (1000 rekordów)~6 ms~150 msx25 szybciej
Wyszukiwanie po indeksie~0.1 ms~2 msx20 szybciej
Rozmiar BD (1000 obiektów)~28 KB~112 KB4 razy mniejszy

Kiedy ObjectBox nie jest optymalny

ObjectBox przegrywa z SQLite w scenariuszach, gdzie potrzebne są złożone zapytania JOIN, funkcje agregujące (SUM, COUNT z grupowaniem) lub integracja z istniejącym schematem SQL. Jeśli projekt już używa SQLite z Room ORM — migracja na ObjectBox będzie wymagać przepisania całej logiki dostępu do danych. ObjectBox nie obsługuje również niestandardowych zapytań SQL — tylko fluent-API. Jednak dla typowych operacji CRUD i buforowania ObjectBox daje wzrost wydajności do 100 razy, co potwierdzają oficjalne benchmarki na urządzeniach Android z różnymi wersjami OS.

Przykłady kodu z ObjectBox

ObjectBox używa adnotacji do definiowania encji. Po kompilacji tworzone są klasy Box z metodami put, get, remove i query. Poniżej przedstawiono typowe operacje dla modelu Task w aplikacji do listy zadań.

Definiowanie encji

Każda encja jest adnotowana @Entity. Pole z @Id staje się kluczem głównym, @Index przyspiesza wyszukiwanie po polu. ObjectBox obsługuje automatyczne generowanie ID przy wartości 0.

kotlin
@Entity
data class Task(
    @Id var id: Long = 0,
    @Index var title: String = "",
    var isCompleted: Boolean = false,
    var priority: Int = 0
)

Operacje CRUD

Box — główna klasa do pracy z encjami. Metoda put() zapisuje lub aktualizuje obiekt, get() odczytuje po ID, remove() usuwa. Wszystkie podstawowe operacje są synchroniczne i wykonywane na wątku wywołującym.

kotlin
val taskBox: Box<Task> = boxStore.boxFor(Task::class.java)

// Tworzenie
val task = Task(title = "Kup produkty", priority = 3)
val newId = taskBox.put(task)

// Odczyt
val savedTask = taskBox.get(newId)

// Aktualizacja
savedTask.isCompleted = true
taskBox.put(savedTask)

// Usuwanie
taskBox.remove(newId)

Zapytania reaktywne

ObjectBox obsługuje zapytania reaktywne przez .subscribe(). Subskrybent otrzymuje powiadomienia przy każdej zmianie danych odpowiadającej warunkom zapytania. Jest to wygodne dla UI, które automatycznie aktualizuje listę przy dodawaniu lub usuwaniu elementów.

kotlin
val query = taskBox.query()
    .equal(Task_.isCompleted, false)
    .orderDesc(Task_.priority)
    .build()

query.subscribe { tasks ->
    // tasks — List, aktualizowana automatycznie
    updateUi(tasks)
}

Relacje i zapytania w ObjectBox

ObjectBox obsługuje relacje między encjami — To-One, To-Many i Many-to-Many. Relacje są definiowane przez adnotację @Relation. W przeciwieństwie do SQLite, ObjectBox nie używa kluczy obcych: relacje są realizowane przez listy ID w płaskich plikach, co przyspiesza nawigację po grafie obiektów.

One-to-Many przez @Backlink

Relacja @Backlink pozwala przejść od encji potomnej do nadrzędnej bez osobnego pola referencji. ObjectBox automatycznie utrzymuje odwrotne odwołanie, co eliminuje duplikację danych i synchronizację między dwiema tabelami.

Zapytania fluent

ObjectBox Query Builder pozwala budować łańcuchy warunków: equal, notEqual, greater, less, in, contains, startsWith. Wszystkie warunki są łączone przez and/or. Wynik można sortować, ograniczać i uzyskać jako List lub LazyList (dla dużych zbiorów danych).

Konfiguracja indeksów dla przyspieszenia wyszukiwania

ObjectBox automatycznie indeksuje pole @Id. Dla niestandardowych indeksów używaj adnotacji @Index na polach, po których często wykonywane są zapytania. Indeksy przyspieszają zapytania equal i in, ale spowalniają wstawianie — nie indeksuj pól, po których wyszukiwanie nie jest wykonywane. ObjectBox obsługuje indeksy złożone do filtrowania po kilku polach jednocześnie. Indeksy złożone są szczególnie przydatne do filtrów na listach: na przykład wyszukiwanie niezakończonych zadań o wysokim priorytecie jest dziesiątki razy szybsze z indeksem złożonym na polach isCompleted i priority.

ObjectBox Sync — synchronizacja między urządzeniami

ObjectBox Sync — autorska technologia do synchronizacji danych między urządzeniami w czasie rzeczywistym. Używa protokołu opartego na WebSocket z rozwiązywaniem konfliktów według last-writer-wins. Sync nadaje się do aplikacji, które potrzebują synchronizacji offline: notatki, listy zadań, dane IoT z wielu czujników. Jednak dla produkcji wymagany jest zakup licencji.

kotlin
// Zapytanie z wieloma warunkami
val highPriorityIncomplete = taskBox.query()
    .greater(Task_.priority, 5)
    .equal(Task_.isCompleted, false)
    .build()
    .find()

// Wyszukiwanie po podłańcuchu
val searchResults = taskBox.query()
    .contains(Task_.title, "produkt", StringOrder.CASE_INSENSITIVE)
    .build()
    .find()

Często zadawane pytania

Czy ObjectBox jest darmowy do użytku komercyjnego?

ObjectBox jest rozpowszechniany na licencji Apache 2.0, która pozwala na komercyjne użycie bez ograniczeń. Funkcja ObjectBox Sync (synchronizacja międzyplatformowa) jest własnościowa i wymaga zakupu licencji dla produkcji.

Czy ObjectBox obsługuje wielowątkowość?

BoxStore jest bezpieczny wątkowo: wiele wątków może jednocześnie odczytywać dane. Zapis jest blokowany na poziomie Box. Dla złożonych transakcji używaj boxStore.runInTx(), który gwarantuje atomowość grupy operacji.

Czy można używać ObjectBox z Kotlin Multiplatform?

Tak, ObjectBox obsługuje Kotlin Multiplatform (KMP) od wersji 3.0. Dostępne są targety Android, iOS, JVM i Native. Dla KMP używany jest osobny plugin Gradle objectbox-kotlin z obsługą expect/actual.

Jak zrobić kopię zapasową bazy ObjectBox?

ObjectBox przechowuje dane w plikach .mdb w katalogu aplikacji. Aby wykonać kopię zapasową, skopiuj cały katalog ObjectBox przez BoxStore.copy() lub ręcznie skopiuj pliki po wywołaniu boxStore.close(). Żywych plików nie można kopiować — uszkodzi to dane.

Czym ObjectBox różni się od Room?

Room — ORM na bazie SQLite, wymaga zapytań SQL i ma narzut na mapowanie obiektów. ObjectBox to NoSQL bez SQL, jest o rząd szybszy, ale nie obsługuje złożonych JOIN i nie jest relacyjną bazą danych. Wybór zależy od zadania: dla danych relacyjnych — Room, dla szybkiego przechowywania obiektów — ObjectBox.

Podsumowanie

  • ObjectBox — NoSQL BD z wydajnością 10–100 razy wyższą niż SQLite na urządzeniach mobilnych
  • Płaskie pliki — własny format SLOT bez warstwy SQL i narzutów ORM
  • Adnotacje — @Entity, @Id, @Index, @Relation do opisu modelu danych
  • Reaktywność — wbudowane Observable i Flow do automatycznej aktualizacji UI
  • Wieloplatformowość — Android, iOS, Linux, macOS, Windows, WebAssembly
  • Buforowanie i offline — główny scenariusz ObjectBox w aplikacjach mobilnych
  • Zalecenie — wybieraj ObjectBox do zadań, gdzie szybkość pracy z danymi jest ważniejsza niż integralność relacyjna

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również