Docs Menu

Docs HomeRealm

Object Models & Schemas - Java SDK

On this page

  • Realm Apps
  • Primary Keys
  • Optionality
  • Relationships
  • Indexes
  • Modules
  • Realm Objects
  • RealmProxy
  • Realm Object Limitations
  • Incremental Builds

An object schema is a configuration object that defines the fields and relationships of a Realm object type. Android Realm applications define object schemas with Java or Kotlin classes using Realm Schemas.

Object schemas specify constraints on object fields such as the data type of each field, whether a field is required, and default field values. Schemas can also define relationships between object types in a realm.

Modifying your application's Realm Schema requires you to migrate data from older versions of your Realm Schema to the new version.

Every App has a Realm Schema composed of a list of object schemas for each type of object that the realms in that application may contain.

Realm guarantees that all objects in a realm conform to the schema for their object type and validates objects whenever they're created, modified, or deleted.

Apps that use Atlas Device Sync can define schemas in two ways:

  • object schemas using Kotlin and Java class declarations with Development Mode.

  • JSON object schemas in your App backend.

New in version 10.6.0: Realm Database automatically indexes primary key fields. Previously, Realm only indexed String primary keys automatically.

Realm treats fields marked with the @PrimaryKey annotation as primary keys for their corresponding object schema. Primary keys are subject to the following limitations:

  • You can define only one primary key per object schema.

  • Primary key values must be unique across all instances of an object in a realm. Attempting to insert a duplicate primary key value results in a RealmPrimaryKeyConstraintException.

  • Primary key values are immutable. To change the primary key value of an object, you must delete the original object and insert a new object with a different primary key value.

  • Embedded objects cannot define a primary key.

You can create a primary key with any of the following types:

  • String

  • UUID

  • ObjectId

  • Integer or int

  • Long or long

  • Short or short

  • Byte or byte[]

Non-primitive types can contain a value of null as a primary key value, but only for one object of a particular type, since each primary key value must be unique. Attempting to insert an object with an existing primary key into a realm will result in a RealmPrimaryKeyConstraintException.

Realm Database automatically indexes primary key fields, which allows you to efficiently read and modify objects based on their primary key.

You cannot change the primary key field for an object type after adding any object of that type to a realm. If you are using Sync, you cannot change the primary key field for an object after defining the primary key in your backend schema.

Embedded objects cannot contain primary keys.


See also:

You can make a field required to disallow null values in a field. Fields marked with Java object types and Kotlin nullable types (ending with ?) are nullable by default. All other types (primitives, non-nullable Kotlin object types) are required by default. You can mark a nullable field with the @Required annotation to prevent that field from holding a null value. RealmLists are never nullable, but you can use the @Required annotation to prevent objects in a list from holding a null value, even if the base type would otherwise allow it. You cannot mark a RealmList of RealmObject subtypes as required.

You can make any of the following types required:

  • String

  • UUID

  • ObjectId

  • Integer

  • Long

  • Short

  • Byte or byte[]

  • Boolean

  • Float

  • Double

  • Date

  • RealmList

Primitive types such as int and the RealmList type are implicitly required. Fields with the RealmObject type are always nullable, and cannot be made required.


Kotlin Types and Nullability

In Kotlin, types are non-nullable by default unless you explicitly add a ? suffix to the type. You can only annotate nullable types. Using the @Required annotation on non-nullable types will fail compilation.

You can model one-to-one relationships in realm with RealmObject fields. You can model one-to-many and many-to-one relationships RealmList fields. Inverse relationships are the opposite end of a one-to-many or many-to-one relationship. You can make inverse relationships traversable with the @LinkingObjects annotation on a RealmResults field. In an instance of a RealmObject, inverse relationship fields contain the set of Realm objects that point to that object instance through the described relationship. You can find the same set of Realm objects with a manual query, but the inverse relationship field reduces boilerplate query code and capacity for error.

Indexes support the efficient execution of queries in Realm Database. Without indexes, Realm Database must perform a collection scan, i.e. scan every document in a collection, to select those documents that match a query. If an appropriate index exists for a query, Realm Database can use the index to limit the number of documents that it must inspect.

Indexes are special data structures that store a small portion of a realm's data in an easy to traverse form. The index stores the value of a specific field ordered by the value of the field. The ordering of the index entries supports efficient equality matches and range-based query operations.

Adding an index can speed up some queries at the cost of slightly slower write times and additional storage and memory overhead. Indexes require space in your realm file, so adding an index to a property will increase disk space consumed by your realm file. Each index entry is a minimum of 12 bytes.

You can index fields with the following types:

  • String

  • UUID

  • ObjectId

  • Integer or int

  • Long or long

  • Short or short

  • Byte or byte[]

  • Boolean or bool

  • Date

  • RealmAny

Realm creates indexes for fields annotated with @Index.

Realm Modules describe the set of Realm objects that can be stored in a realm. By default, Realm automatically creates a Realm Module that contains all Realm objects defined in your application. You can define a RealmModule to restrict a realm to a subset of classes defined in an application. If you produce a library that uses Realm, you can use a Realm Module to explicitly include only the Realm objects defined in your library in your realm. This allows applications that include your library to also use Realm without managing object name conflicts and migrations with your library's defined Realm objects.

Unlike normal Java objects, which contain their own data, a Realm object doesn't contain data. Instead, Realm objects read and write properties directly to Realm Database.

Instances of Realm objects can be either managed or unmanaged.

  • Managed objects are:

    • persisted in Realm Database

    • always up to date

    • thread-confined

    • generally more lightweight than the unmanaged version, as they take up less space on the Java heap.

  • Unmanaged objects are just like ordinary Java objects, since they are not persisted and never update automatically. You can move unmanaged objects freely across threads.

You can convert between the two states using realm.copyToRealm() and realm.copyFromRealm().

The RealmProxy classes are the Realm SDK's way of ensuring that Realm objects don't contain any data themselves. Instead, each class's RealmProxy accesses data directly in the database.

For every model class in your project, the Realm annotation processor generates a corresponding RealmProxy class. This class extends your model class and is returned when you call Realm.createObject(). In your code, this object works just like your model class.

Realm objects:

  • cannot contain fields that use the final or volatile modifiers (except for inverse relationship fields).

  • cannot extend any object other than RealmObject.

  • must contain an empty constructor (if your class does not include any constructor, the automatically generated empty constructor will suffice)

Naming limitations:

  • Class names cannot exceed 57 characters.

  • Class names must be unique within realm modules

  • Field names cannot exceed 63 characters.

Size limitations:

  • String or byte[] fields cannot exceed 16 MB.

Usage limitations:

  • Because Realm objects are live and can change at any time, their hashCode() value can change over time. As a result, you should not use RealmObject instances as a key in any map or set.

The bytecode transformer used by Realm supports incremental builds, but your application requires a full rebuild when adding or removing the following from a Realm object field:

  • an @Ignore annotation

  • the static keyword

  • the transient keyword

You can perform a full rebuild with Build > Clean Project and Build > Rebuild Project in these cases.

←  Relationships - Java SDKSchema Versions & Migrations - Java SDK →
Share Feedback
© 2023 MongoDB, Inc.


  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2023 MongoDB, Inc.