Package io.objectbox

Class BoxStore

  • All Implemented Interfaces:
    java.io.Closeable, java.lang.AutoCloseable

    @ThreadSafe
    public class BoxStore
    extends java.lang.Object
    implements java.io.Closeable
    An ObjectBox database that provides Boxes to put and get objects of specific entity classes (see boxFor(Class)). To get an instance of this class use MyObjectBox.builder().
    • Field Detail

      • context

        @Nullable
        private static java.lang.Object context
        On Android used for native library loading.
      • relinker

        @Nullable
        private static java.lang.Object relinker
      • IN_MEMORY_PREFIX

        public static final java.lang.String IN_MEMORY_PREFIX
        Prefix supplied with database directory to signal a file-less and in-memory database should be used.
        See Also:
        Constant Field Values
      • JNI_VERSION

        public static final java.lang.String JNI_VERSION
        ReLinker uses this as a suffix for the extracted shared library file. If different, it will update it.
        See Also:
        Constant Field Values
      • VERSION

        private static final java.lang.String VERSION
        The native or core version of ObjectBox the Java library is known to work with.
        See Also:
        Constant Field Values
      • defaultStore

        private static BoxStore defaultStore
      • openFiles

        private static final java.util.Set<java.lang.String> openFiles
        Currently used DB dirs with values from getCanonicalPath(File).
      • openFilesCheckerThread

        private static volatile java.lang.Thread openFilesCheckerThread
      • directory

        private final java.io.File directory
      • canonicalPath

        private final java.lang.String canonicalPath
      • handle

        private volatile long handle
        Reference to the native store. Should probably get through getNativeStore() instead.
      • dbNameByClass

        private final java.util.Map<java.lang.Class<?>,​java.lang.String> dbNameByClass
      • entityTypeIdByClass

        private final java.util.Map<java.lang.Class<?>,​java.lang.Integer> entityTypeIdByClass
      • propertiesByClass

        private final java.util.Map<java.lang.Class<?>,​EntityInfo<?>> propertiesByClass
      • classByEntityTypeId

        private final org.greenrobot.essentials.collections.LongHashMap<java.lang.Class<?>> classByEntityTypeId
      • allEntityTypeIds

        private final int[] allEntityTypeIds
      • boxes

        private final java.util.Map<java.lang.Class<?>,​Box<?>> boxes
      • transactions

        private final java.util.Set<Transaction> transactions
      • threadPool

        private final java.util.concurrent.ExecutorService threadPool
      • debugTxRead

        final boolean debugTxRead
      • debugTxWrite

        final boolean debugTxWrite
      • debugRelations

        final boolean debugRelations
      • activeTx

        final java.lang.ThreadLocal<Transaction> activeTx
        Set when running inside TX
      • closed

        private volatile boolean closed
      • txCommitCountLock

        final java.lang.Object txCommitCountLock
      • commitCount

        volatile int commitCount
      • objectBrowserPort

        private int objectBrowserPort
      • queryAttempts

        private final int queryAttempts
      • failedReadTxAttemptCallback

        private final TxCallback<?> failedReadTxAttemptCallback
      • syncClient

        @Nullable
        private SyncClient syncClient
        Keeps a reference so the library user does not have to.
    • Method Detail

      • getContext

        @Nullable
        @Internal
        public static java.lang.Object getContext()
      • getRelinker

        @Nullable
        @Internal
        public static java.lang.Object getRelinker()
      • getDefault

        public static BoxStore getDefault()
        Convenience singleton instance which gets set up using BoxStoreBuilder.buildDefault().

        Note: for better testability, you can usually avoid singletons by storing a BoxStore instance in some application scope object and pass it along.

      • setDefault

        static void setDefault​(BoxStore store)
      • clearDefaultStore

        public static boolean clearDefaultStore()
        Clears the convenience instance.

        Note: This is usually not required (for testability, please see the comment of getDefault()).

        Returns:
        true if a default store was available before
      • getVersion

        public static java.lang.String getVersion()
        Gets the Version of ObjectBox Java.
      • nativeGetVersion

        static java.lang.String nativeGetVersion()
      • getVersionNative

        public static java.lang.String getVersionNative()
        Gets the Version of ObjectBox Core.
      • nativeRemoveDbFiles

        static boolean nativeRemoveDbFiles​(java.lang.String directory,
                                           boolean removeDir)
        Returns:
        true if DB files did not exist or were successfully removed, false if DB files exist that could not be removed.
      • nativeCreateWithFlatOptions

        static long nativeCreateWithFlatOptions​(byte[] options,
                                                byte[] model)
        Creates a native BoxStore instance with FlatBuffer FlatStoreOptions options and a ModelBuilder model. Returns the handle of the native store instance.
      • nativeIsReadOnly

        static boolean nativeIsReadOnly​(long store)
      • nativeDelete

        static void nativeDelete​(long store)
      • nativeDropAllData

        static void nativeDropAllData​(long store)
      • nativeGloballyActiveEntityTypes

        @Internal
        static long nativeGloballyActiveEntityTypes()
        A static counter for the alive entity types (entity schema instances); this can be useful to test against leaks. This number depends on the number of currently opened stores; no matter how often stores were closed and (re-)opened. E.g. when stores are regularly opened, but not closed by the user, the number should increase. When all stores are properly closed, this value should be 0.
      • nativeBeginTx

        static long nativeBeginTx​(long store)
      • nativeBeginReadTx

        static long nativeBeginReadTx​(long store)
      • nativeRegisterEntityClass

        static int nativeRegisterEntityClass​(long store,
                                             java.lang.String entityName,
                                             java.lang.Class<?> entityClass)
        Returns:
        entity ID
      • nativeRegisterCustomType

        static void nativeRegisterCustomType​(long store,
                                             int entityId,
                                             int propertyId,
                                             java.lang.String propertyName,
                                             java.lang.Class<? extends PropertyConverter> converterClass,
                                             java.lang.Class<?> customType)
      • nativeDiagnose

        static java.lang.String nativeDiagnose​(long store)
      • nativeCleanStaleReadTransactions

        static int nativeCleanStaleReadTransactions​(long store)
      • nativeSetDbExceptionListener

        static void nativeSetDbExceptionListener​(long store,
                                                 @Nullable
                                                 DbExceptionListener dbExceptionListener)
      • nativeSetDebugFlags

        static void nativeSetDebugFlags​(long store,
                                        int debugFlags)
      • nativeStartObjectBrowser

        private java.lang.String nativeStartObjectBrowser​(long store,
                                                          @Nullable
                                                          java.lang.String urlPath,
                                                          int port)
      • nativeStopObjectBrowser

        private boolean nativeStopObjectBrowser​(long store)
      • nativeIsObjectBrowserAvailable

        static boolean nativeIsObjectBrowserAvailable()
      • nativeDbSize

        long nativeDbSize​(long store)
      • nativeDbSizeOnDisk

        long nativeDbSizeOnDisk​(long store)
      • nativeValidate

        long nativeValidate​(long store,
                            long pageLimit,
                            boolean checkLeafLevel)
      • nativeSysProcMeminfoKb

        static long nativeSysProcMeminfoKb​(java.lang.String key)
      • nativeSysProcStatusKb

        static long nativeSysProcStatusKb​(java.lang.String key)
      • nativeHasFeature

        private static boolean nativeHasFeature​(int feature)
      • hasFeature

        public static boolean hasFeature​(Feature feature)
      • isObjectBrowserAvailable

        public static boolean isObjectBrowserAvailable()
      • isSyncAvailable

        public static boolean isSyncAvailable()
      • isSyncServerAvailable

        public static boolean isSyncServerAvailable()
      • nativePanicModeRemoveAllObjects

        long nativePanicModeRemoveAllObjects​(long store,
                                             int entityId)
      • getCanonicalPath

        static java.lang.String getCanonicalPath​(java.io.File directory)
      • verifyNotAlreadyOpen

        static void verifyNotAlreadyOpen​(java.lang.String canonicalPath)
      • isFileOpen

        static boolean isFileOpen​(java.lang.String canonicalPath)
        Also retries up to 500ms to improve GC race condition situation.
      • isFileOpenSync

        static boolean isFileOpenSync​(java.lang.String canonicalPath,
                                      boolean runFinalization)
      • isDatabaseOpen

        public static boolean isDatabaseOpen​(java.lang.Object context,
                                             @Nullable
                                             java.lang.String dbNameOrNull)
                                      throws java.io.IOException
        Using an Android Context and an optional database name, as configured with BoxStoreBuilder.name(String), checks if the associated database files are in use by a BoxStore instance.

        Use this to check that database files are not open before copying or deleting them.

        Throws:
        java.io.IOException
      • isDatabaseOpen

        public static boolean isDatabaseOpen​(@Nullable
                                             java.io.File baseDirectoryOrNull,
                                             @Nullable
                                             java.lang.String dbNameOrNull)
                                      throws java.io.IOException
        Using an optional base directory, as configured with BoxStoreBuilder.baseDirectory(File), and an optional database name, as configured with BoxStoreBuilder.name(String), checks if the associated database files are in use by a BoxStore instance.

        Use this to check that database files are not open before copying or deleting them.

        Throws:
        java.io.IOException
      • isDatabaseOpen

        public static boolean isDatabaseOpen​(java.io.File directory)
                                      throws java.io.IOException
        Using a directory, as configured with BoxStoreBuilder.directory(File), checks if the associated database files are in use by a BoxStore instance.

        Use this to check that database files are not open before copying or deleting them.

        Throws:
        java.io.IOException
      • sysProcMeminfoKb

        @Experimental
        public static long sysProcMeminfoKb​(java.lang.String key)
        Linux only: extracts a kB value from /proc/meminfo (system wide memory information). A couple of interesting keys (from 'man proc'): - MemTotal: Total usable RAM (i.e., physical RAM minus a few reserved bits and the kernel binary code). - MemFree: The sum of LowFree+HighFree. - MemAvailable: An estimate of how much memory is available for starting new applications, without swapping.
        Parameters:
        key - The string identifying the wanted line from /proc/meminfo to extract a Kb value from. E.g. "MemTotal".
        Returns:
        Kb value or 0 on failure
      • sysProcStatusKb

        @Experimental
        public static long sysProcStatusKb​(java.lang.String key)
        Linux only: extracts a kB value from /proc/self/status (process specific information). A couple of interesting keys (from 'man proc'): - VmPeak: Peak virtual memory size. - VmSize: Virtual memory size. - VmHWM: Peak resident set size ("high water mark"). - VmRSS: Resident set size. Note that the value here is the sum of RssAnon, RssFile, and RssShmem. - RssAnon: Size of resident anonymous memory. (since Linux 4.5). - RssFile: Size of resident file mappings. (since Linux 4.5). - RssShmem: Size of resident shared memory (includes System V shared memory, mappings from tmpfs(5), and shared anonymous mappings). (since Linux 4.5). - VmData, VmStk, VmExe: Size of data, stack, and text segments. - VmLib: Shared library code size.
        Parameters:
        key - The string identifying the wanted line from /proc/self/status to extract a Kb value from. E.g. "VmSize".
        Returns:
        Kb value or 0 on failure
      • sizeOnDisk

        @Deprecated
        public long sizeOnDisk()
        Deprecated.
        Use getDbSize() or getDbSizeOnDisk() instead which properly handle in-memory databases.
        The size in bytes occupied by the data file on disk.
        Returns:
        0 if the size could not be determined (does not throw unless this store was already closed)
      • getDbSize

        public long getDbSize()
        Get the size of this store. For a disk-based store type, this corresponds to the size on disk, and for the in-memory store type, this is roughly the used memory bytes occupied by the data.
        Returns:
        The size in bytes of the database, or 0 if the file does not exist or some error occurred.
      • getDbSizeOnDisk

        public long getDbSizeOnDisk()
        The size in bytes occupied by the database on disk (if any).
        Returns:
        The size in bytes of the database on disk, or 0 if the underlying database is in-memory only or the size could not be determined.
      • finalize

        protected void finalize()
                         throws java.lang.Throwable
        Closes this if this is finalized.

        Explicitly call close() instead to avoid expensive finalization.

        Overrides:
        finalize in class java.lang.Object
        Throws:
        java.lang.Throwable
      • checkOpen

        private void checkOpen()
        Verifies this has not been closed.
      • getDbName

        java.lang.String getDbName​(java.lang.Class<?> entityClass)
      • getEntityTypeId

        java.lang.Integer getEntityTypeId​(java.lang.Class<?> entityClass)
      • getEntityTypeIdOrThrow

        @Internal
        public int getEntityTypeIdOrThrow​(java.lang.Class<?> entityClass)
      • getAllEntityClasses

        public java.util.Collection<java.lang.Class<?>> getAllEntityClasses()
      • getAllEntityTypeIds

        @Internal
        int[] getAllEntityTypeIds()
      • getEntityClassOrThrow

        @Internal
        java.lang.Class<?> getEntityClassOrThrow​(int entityTypeId)
      • getEntityInfo

        @Internal
        <T> EntityInfo<T> getEntityInfo​(java.lang.Class<T> entityClass)
      • beginReadTx

        @Internal
        public Transaction beginReadTx()
        Internal, low level method: use runInReadTx(Runnable) instead. Begins a transaction for read access only. Note: there may be only one read transaction per thread.
      • isClosed

        public boolean isClosed()
        If this was closed.
      • isReadOnly

        public boolean isReadOnly()
        Whether the store was created using read-only mode. If true the schema is not updated and write transactions are not possible.
      • close

        public void close()
        Closes this BoxStore and releases associated resources.

        Before calling, all database operations must have finished (there are no more active transactions).

        If that is not the case, the method will briefly wait on any active transactions, but then will forcefully close them to avoid crashes and print warning messages ("Transactions are still active"). If this occurs, analyze your code to make sure all database operations, notably in other threads or data observers, are properly finished.

        Specified by:
        close in interface java.lang.AutoCloseable
        Specified by:
        close in interface java.io.Closeable
      • checkThreadTermination

        private void checkThreadTermination()
        dump thread stacks if pool does not terminate promptly.
      • deleteAllFiles

        public boolean deleteAllFiles()
        Danger zone! This will delete all data (files) of this BoxStore! You must call close() before and read the docs of that method carefully!

        A safer alternative: use the static deleteAllFiles(File) method before opening the BoxStore.

        Returns:
        true if the directory 1) was deleted successfully OR 2) did not exist in the first place. Note: If false is returned, any number of files may have been deleted before the failure happened.
      • deleteAllFiles

        public static boolean deleteAllFiles​(java.io.File objectStoreDirectory)
        Danger zone! This will delete all files in the given directory!

        No BoxStore may be alive using the given directory. E.g. call this before building a store. When calling this after closing a store, read the docs of that method carefully first!

        If no name was specified when building the store, use like:

        
             BoxStore.deleteAllFiles(new File(BoxStoreBuilder.DEFAULT_NAME));
         

        For an in-memory database, this will just clean up the in-memory database.

        Parameters:
        objectStoreDirectory - directory to be deleted; this is the value you previously provided to BoxStoreBuilder.directory(File)
        Returns:
        true if the directory 1) was deleted successfully OR 2) did not exist in the first place. Note: If false is returned, any number of files may have been deleted before the failure happened.
        Throws:
        java.lang.IllegalStateException - if the given directory is still used by an open BoxStore.
      • deleteAllFiles

        public static boolean deleteAllFiles​(java.lang.Object androidContext,
                                             @Nullable
                                             java.lang.String customDbNameOrNull)
        Danger zone! This will delete all files in the given directory!

        No BoxStore may be alive using the given name.

        If you did not use a custom name with BoxStoreBuilder, you can pass "new File(BoxStoreBuilder.DEFAULT_NAME)".

        Parameters:
        androidContext - provide an Android Context like Application or Service
        customDbNameOrNull - use null for default name, or the name you previously provided to BoxStoreBuilder.name(String).
        Returns:
        true if the directory 1) was deleted successfully OR 2) did not exist in the first place. Note: If false is returned, any number of files may have been deleted before the failure happened.
        Throws:
        java.lang.IllegalStateException - if the given name is still used by a open BoxStore.
      • deleteAllFiles

        public static boolean deleteAllFiles​(@Nullable
                                             java.io.File baseDirectoryOrNull,
                                             @Nullable
                                             java.lang.String customDbNameOrNull)
        Danger zone! This will delete all files in the given directory!

        No BoxStore may be alive using the given directory.

        If you did not use a custom name with BoxStoreBuilder, you can pass "new File(BoxStoreBuilder.DEFAULT_NAME)".

        Parameters:
        baseDirectoryOrNull - use null for no base dir, or the value you previously provided to BoxStoreBuilder.baseDirectory(File)
        customDbNameOrNull - use null for default name, or the name you previously provided to BoxStoreBuilder.name(String).
        Returns:
        true if the directory 1) was deleted successfully OR 2) did not exist in the first place. Note: If false is returned, any number of files may have been deleted before the failure happened.
        Throws:
        java.lang.IllegalStateException - if the given directory (+name) is still used by a open BoxStore.
      • removeAllObjects

        public void removeAllObjects()
        Removes all objects from all types ("boxes"), e.g. deletes all database content (excluding meta data like the data model). This typically performs very quickly (e.g. faster than Box.removeAll()).

        Note that this does not reclaim disk space: the already reserved space for the DB file(s) is used in the future resulting in better performance because no/less disk allocation has to be done.

        If you want to reclaim disk space, delete the DB file(s) instead:

      • hasActiveTransaction

        private boolean hasActiveTransaction()
        Returns if transactions has a single transaction that isActive().

        Callers must synchronize on transactions.

      • txCommitted

        void txCommitted​(Transaction tx,
                         @Nullable
                         int[] entityTypeIdsAffected)
      • boxFor

        public <T> Box<T> boxFor​(java.lang.Class<T> entityClass)
        Returns a Box for the given type. Objects are put into (and get from) their individual Box.

        Creates a Box only once and then always returns the cached instance.

      • runInTx

        public void runInTx​(java.lang.Runnable runnable)
        Runs the given runnable inside a transaction.

        Efficiency notes: it is advised to run multiple puts in a transaction because each commit requires an expensive disk synchronization.

      • runInReadTx

        public void runInReadTx​(java.lang.Runnable runnable)
        Runs the given runnable inside a read(-only) transaction. Multiple read transactions can occur at the same time. This allows multiple read operations (gets) using a single consistent state of data. Also, for a high number of read operations (thousands, e.g. in loops), it is advised to run them in a single read transaction for efficiency reasons.
      • callInReadTxWithRetry

        @Experimental
        public <T> T callInReadTxWithRetry​(java.util.concurrent.Callable<T> callable,
                                           int attempts,
                                           int initialBackOffInMs,
                                           boolean logAndHeal)
        Calls callInReadTx(Callable) and retries in case a DbException is thrown. If the given amount of attempts is reached, the last DbException will be thrown. Experimental: API might change.
      • callInReadTx

        public <T> T callInReadTx​(java.util.concurrent.Callable<T> callable)
        Calls the given callable inside a read(-only) transaction. Multiple read transactions can occur at the same time. This allows multiple read operations (gets) using a single consistent state of data. Also, for a high number of read operations (thousands, e.g. in loops), it is advised to run them in a single read transaction for efficiency reasons. Note that an exception thrown by the given Callable will be wrapped in a RuntimeException, if the exception is not a RuntimeException itself.
      • callInTx

        public <R> R callInTx​(java.util.concurrent.Callable<R> callable)
                       throws java.lang.Exception
        Like runInTx(Runnable), but allows returning a value and throwing an exception.
        Throws:
        java.lang.Exception
      • callInTxNoException

        public <R> R callInTxNoException​(java.util.concurrent.Callable<R> callable)
        Like callInTx(Callable), but throws no Exception. Any Exception thrown in the Callable is wrapped in a RuntimeException.
      • runInTxAsync

        public void runInTxAsync​(java.lang.Runnable runnable,
                                 @Nullable
                                 TxCallback<java.lang.Void> callback)
        Runs the given Runnable as a transaction in a separate thread. Once the transaction completes the given callback is called (callback may be null).

        See also runInTx(Runnable).

      • callInTxAsync

        public <R> void callInTxAsync​(java.util.concurrent.Callable<R> callable,
                                      @Nullable
                                      TxCallback<R> callback)
        Runs the given Runnable as a transaction in a separate thread. Once the transaction completes the given callback is called (callback may be null).

        * See also callInTx(Callable).

      • diagnose

        public java.lang.String diagnose()
        Gives info that can be useful for debugging.
        Returns:
        String that is typically logged by the application.
      • validate

        @Beta
        public long validate​(long pageLimit,
                             boolean checkLeafLevel)
        Validate database pages, a lower level storage unit (integrity check). Do not call this inside a transaction (currently unsupported).
        Parameters:
        pageLimit - the maximum of pages to validate (e.g. to limit time spent on validation). Pass zero set no limit and thus validate all pages.
        checkLeafLevel - Flag to validate leaf pages. These do not point to other pages but contain data.
        Returns:
        Number of pages validated, which may be twice the given pageLimit as internally there are "two DBs".
        Throws:
        DbException - if validation failed to run (does not tell anything about DB file consistency).
        FileCorruptException - if the DB file is actually inconsistent (corrupt).
      • cleanStaleReadTransactions

        public int cleanStaleReadTransactions()
      • closeThreadResources

        public void closeThreadResources()
        Call this method from a thread that is about to be shutdown or likely not to use ObjectBox anymore: it frees any cached resources tied to the calling thread (e.g. readers). This method calls Box.closeThreadResources() for all initiated boxes (boxFor(Class)).
      • subscribe

        public SubscriptionBuilder<java.lang.Class> subscribe()
        A DataObserver can be subscribed to data changes using the returned builder. The observer is supplied via SubscriptionBuilder.observer(DataObserver) and will be notified once a transaction is committed and will receive changes to any object class.

        Threading notes: All observers are notified from one separate thread (pooled). Observers are not notified in parallel. The notification order is the same as the subscription order, although this may not always be guaranteed in the future.

        Note that failed or aborted transaction do not trigger observers.

      • subscribe

        public <T> SubscriptionBuilder<java.lang.Class<T>> subscribe​(java.lang.Class<T> forClass)
        Like subscribe(), but wires the supplied @DataObserver only to the given object class for notifications.
      • startObjectBrowser

        @Experimental
        @Nullable
        public java.lang.String startObjectBrowser()
      • startObjectBrowser

        @Experimental
        @Nullable
        public java.lang.String startObjectBrowser​(int port)
      • startObjectBrowser

        @Experimental
        @Nullable
        public java.lang.String startObjectBrowser​(java.lang.String urlToBindTo)
      • stopObjectBrowser

        @Experimental
        public boolean stopObjectBrowser()
      • getObjectBrowserPort

        @Experimental
        public int getObjectBrowserPort()
      • isObjectBrowserRunning

        public boolean isObjectBrowserRunning()
      • verifyObjectBrowserNotRunning

        private void verifyObjectBrowserNotRunning()
      • setDbExceptionListener

        public void setDbExceptionListener​(@Nullable
                                           DbExceptionListener dbExceptionListener)
        Sets a listener that will be called when an exception is thrown. Replaces a previously set listener. Set to null to remove the listener.

        This for example allows central error handling or special logging for database-related exceptions.

      • internalScheduleThread

        @Internal
        public java.util.concurrent.Future<?> internalScheduleThread​(java.lang.Runnable runnable)
      • internalThreadPool

        @Internal
        public java.util.concurrent.ExecutorService internalThreadPool()
      • isDebugRelations

        @Internal
        public boolean isDebugRelations()
      • internalQueryAttempts

        @Internal
        public int internalQueryAttempts()
      • internalFailedReadTxAttemptCallback

        @Internal
        public TxCallback<?> internalFailedReadTxAttemptCallback()
      • setDebugFlags

        void setDebugFlags​(int debugFlags)
      • panicModeRemoveAllObjects

        long panicModeRemoveAllObjects​(int entityId)
      • getNativeStore

        public long getNativeStore()
        Gets the reference to the native store. Can be used with the C API to use the same store, e.g. via JNI, by passing it on to obx_store_wrap().

        Throws if the store is closed.

        The procedure is like this:
        1) you create a BoxStore on the Java side
        2) you call this method to get the native store pointer
        3) you pass the native store pointer to your native code (e.g. via JNI)
        4) your native code calls obx_store_wrap() with the native store pointer to get a OBX_store pointer
        5) Using the OBX_store pointer, you can use the C API.

        Note: Once you close() this BoxStore, do not use it from the C API.

      • isNativeStoreClosed

        @Internal
        public boolean isNativeStoreClosed()
        For internal use only. This API might change or be removed with a future release.

        Returns if the native Store was closed.

        This is true shortly after close() was called and isClosed() returns true.

      • getSyncClient

        @Nullable
        public SyncClient getSyncClient()
        Returns the SyncClient associated with this store. To create one see Sync.
      • setSyncClient

        void setSyncClient​(@Nullable
                           SyncClient syncClient)