- Object Models & Schemas — Android SDKВ¶
- Realm Apps¶
- Primary Keys¶
- Optionality¶
- Read & Write Data — Android SDKВ¶
- About the Examples on this Page¶
- Read from Realm Database¶
- Primary key realm android
- The Default Realm
- Opening a Synchronized Realm
- Other Realms
- Schema Version
- Synchronously Opening Realms
- Models
- Classes
- Supported types
- Optional Properties
- List Properties
- Relationships
- To-One Relationships
- To-Many Relationships
- Inverse Relationships
- Default Property Values
- Indexed Properties
- Primary Keys
- Writes
- Creating Objects
- Nested Objects
- Updating Objects
- Typed Updates
- Creating and Updating Objects With Primary Keys
- Deleting Objects
- Queries
- Filtering
- Sorting
- Auto-Updating Results
- Limiting Results
- Migrations
- Performing a Migration
- Linear Migrations
- Notifications
- Realm Notifications
- Collection Notifications
- Working with a Synchronized Realm
- Encryption
- Examples
- Troubleshooting
- Missing Realm Constructor
- Chrome Debugging is slow
- Cannot download realm-sync-cocoa
- Crash Reporting
Object Models & Schemas — Android SDKВ¶
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 Object Models.
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 Object Model requires you to migrate data from older versions of your Realm Object Model to the new version.
Realm Apps¶
Every Realm 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.
MongoDB 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.
Realm apps that take advantage of Realm Sync can define schemas in two ways:
Primary Keys¶
New in version 10.6.0: Realm Database automatically indexes primary key fields. Previously, only String fields were automatically indexed.
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 Realm 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.
Optionality¶
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:
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.
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.
Источник
Read & Write Data — Android SDKВ¶
About the Examples on this Page¶
The examples on this page use the data model of a project management app that has two Realm object types: Project and Task . A Project has zero or more Tasks .
See the schema for these two classes, Project and Task , below:
Read from Realm Database¶
A read from a realm generally consists of the following steps:
- Get all objects of a certain type from the realm.
- Optionally, filter the results using the query engine.
- Optionally, sort the results.
All query, filter, and sort operations return a results collection. The results collections are live, meaning they always contain the latest results of the associated query.
By default, you can only read or write to a realm in your application’s UI thread using asynchronous transactions. That is, you can only use Realm methods whose name ends with the word Async in the main thread of your Android application unless you explicitly allow the use of synchronous methods.
This restriction exists for the benefit of your application users: performing read and write operations on the UI thread can lead to unresponsive or slow UI interactions, so it’s usually best to handle these operations either asynchronously or in a background thread. However, if your application requires the use of synchronous realm reads or writes on the UI thread, you can explicitly allow the use of synchronous methods with the following SyncConfiguration options:
Источник
Primary key realm android
Opening a Realm is simply performed by calling the static open method on the Realm class. Pass a configuration object. We’ve seen this used already in the example with a configuration object that includes the schema key:
For full details about the configuration object, see the API Reference for configuration. Some of the more common keys for the object, beyond schema , include:
- path : specify a path to another Realm
- migration : a migration function
- sync : a sync object, to open a Realm synchronized with the Realm Cloud
- inMemory : the Realm will be opened in-memory, and objects are not persisted; once the last Realm instance is closed, all objects vanish
- deleteRealmIfMigrationNeeded : delete the Realm if migration is needed; this is useful under development since the data model might change often
Remember to use the close() method on opened realms when you are done with them.
The Default Realm
You may have noticed in all previous examples that the path argument has been omitted. In this case the default Realm path is used. You can access and change the default Realm path using the Realm.defaultPath global property.
Opening a Synchronized Realm
Are you looking to use Realm Mobile Platform to synchronize all of your Realm Databases? All sync related documentation has been moved to our platform documentation
Other Realms
It’s sometimes useful to have multiple Realms persisted at different locations. For example, you may want to bundle some data with your application in a Realm file, in addition to your main Realm. You can do this by specifying the path argument when initializing your realm. All paths are relative to the writable documents directory for your application:
Schema Version
Another option available when opening a Realm is the schemaVersion property. When omitted, the schemaVersion property defaults to 0 . You are required to specify the schemaVersion when initializing an existing Realm with a schema that contains objects that differ from their previous specification. If the schema was updated and the schemaVersion was not, an exception will be thrown.
If you then later do something like this:
If you wish to retrieve the current schema version of a Realm, you may do so with the Realm.schemaVersion method.
Synchronously Opening Realms
You can create a realm instance by simply invoking the constructor and passing a configuration object to it. This is typically not recommended as it blocks and could potentially be a time consuming operation, especially if there are migrations to run or if the realm is synchronized and you don’t want to risk modifying data before it’s been completely downloaded.
If you still want to do this, the pattern is simple:
Models
Realm data models are defined by the schema information passed into a Realm during initialization. The schema for an object consists of the object’s name and a set of properties. Each property has a name and is described by either a string containing the property’s type, or an object with name , type , objectType , optional , default , and indexed fields.
To avoid size limitations and a performance impact, it is best not to store large blobs (such as image and video files) directly in Realm. Instead, save the file to a file store (such as S3) and keep only the location of the file and any relevant metadata in Realm.
Classes
If you want to use ES2015 classes (and maybe want to inherit existing features), you just need to define the schema on the constructor:
You can now pass the class itself to the schema property of the open configuration:
You access properties as always:
Supported types
Realm supports the following basic types: bool , int , float , double , string , data , and date .
- bool properties map to JavaScript boolean values
- int , float , and double properties map to JavaScript number values. Internally вЂint’ and вЂdouble’ are stored as 64 bits while float is stored with 32 bits.
- string properties map to string
- data properties map to ArrayBuffer
- date properties map to Date
When specifying basic properties as a shorthand you may specify only the type rather than having to specify a dictionary with a single entry:
Optional Properties
By default, basic types are non-optional and do not support storing null or undefined . Properties can be made optional by specifying the optional designator in your property definition, or with the shorthand syntax, by appending a ? to the type name:
List Properties
In addition to storing individual values, properties can also be declared as a list of any of the supported basic types. This is done by appending [] to the type name:
When accessing list properties a List object is returned. List has methods very similar to a regular JavaScript array. The big difference is that any changes made to a List are automatically persisted to the underlying Realm, and as such they can only be modified in write transactions. Additionally, List s belong to the underlying object they were acquired from — you can only get List instances by accessing a property from an owning object and they cannot be manually created.
While the values in a list property can be made optional, the list property itself cannot be. Specifying a list property as optional using the longhand syntax ( values:
Relationships
To-One Relationships
For to-one relationships you specify the name property of the object schema you are referencing as the property’s type:
When using object properties you need to make sure all referenced types are present in the schema used to open the Realm:
When accessing object properties, you can access nested properties using normal property syntax:
Object properties in Realm are always optional, do not have to be explicitly specified as such, and cannot be made required.
To-Many Relationships
Just as with basic properties, you can also have a list of objects to form a to-many relationship. This is done by either appending [] to the name of the target object schema, or by setting the property type to list and specifying the objectType :
Unlike other lists and to-one relationships, to-many relationships cannot be made optional.
Inverse Relationships
Links are unidirectional. So if a to-many property Person.dogs links to Dog instances and a to-one property Dog.owner links to Person , these links are independent from one another. Appending a Dog to a Person instance’s dogs property doesn’t automatically set the dog’s owner property to this Person . Because manually synchronizing pairs of relationships is error prone, complex and duplicates information, Realm provides linking objects properties to represent these inverse relationships.
With linking objects properties, you can obtain all objects that link to a given object from a specific property. For example, a Dog object can have a property named owners that contains all of the Person objects that have this exact Dog object in their dogs property. This is done by making the owners property of type linkingObjects and then specifying the relationship that it has with the Person object.
A linkingObjects property can point either to a List property (to-many relationship) or an Object property (to-one relationship):
When accessing linkingObjects properties, a Results object is returned, so further querying and sorting are fully supported. linkingObject properties belong to the object they were acquired from and can not be set or manipulated directly. They are updated automatically when a transaction is committed.
Accessing linkingObjects without a schema: if you have opened a Realm file without specifying a schema, e.g. in a Realm Functions callback, you can get a linkingObjects property by calling linkingObjects(objectType, property) on an Object instance:
Linking objects properties cannot be made optional.
Default Property Values
Default property values can be specified by setting the default designator in the property definition. To use a default value, leave the property unspecified during object creation.
Indexed Properties
You can add an indexed designator to a property definition to cause that property to be indexed. This is supported for int , string , bool , and date property types:
Indexing a property will greatly speed up queries where the property is compared for equality at the cost of slower insertions.
Primary Keys
You can specify the primaryKey property in an object model for string and int properties. Declaring a primary key allows objects to be looked up and updated efficiently and enforces uniqueness for each value. Once an object with a primary key has been added to a Realm the primary key cannot be changed.
Primary key properties are automatically indexed.
Writes
Changes to objects in a Realm—creating, updating and deleting—must take place within a write() transaction block. Note that write transactions have a non-negligible overhead; you should try to minimize the number of write blocks within your code.
Creating Objects
Objects are created using the create method:
Note that any exceptions thrown in write() will cancel the transaction. The try/catch block won’t be shown in all examples, but it’s good practice.
Nested Objects
If an object has object properties, values for those properties can be created recursively by specifying JSON values for each child property:
Updating Objects
Typed Updates
You can update any object by setting its properties within a write transaction.
Creating and Updating Objects With Primary Keys
If your model class includes a primary key, you can have Realm intelligently update or add objects based off of their primary key values. This is done by passing true as the third argument to the create method:
In the example above, since an object already exists with the id value of 1 and we have passed in ‘modify’ for the third argument, the price property is updated rather than trying to create a new object. Since the title property is omitted the object retains the original value for this property. Note that when creating or updating objects with primary key properties the primary key must be specified.
Deleting Objects
Objects can be deleted by calling the delete method within a write transaction.
Queries
Queries allow you to get objects of a single type from a Realm, with the option of filtering and sorting those results. All queries (including queries and property access) are lazy in Realm. Data is only read when objects and properties are accessed. This allows you to represent large sets of data in a performant way.
When performing queries you are returned a Results object. Results are simply a view of your data and are not mutable.
The most basic method for retrieving objects from a Realm is using the objects method on a Realm to get all objects of a given type:
Filtering
You can get a filtered Results by calling the filtered method on a List or a Results with a query string.
For example, the following would change our earlier example to retrieve all dogs with the color tan and names beginning with вЂB’:
Complex filters that also involve sorting and/or limiting should be handled within the same filtered call for better performance. For example, to find all dogs with the color tan, names beginning with вЂB’, sorting in descending order, and limiting the results to 5:
The query language supported by Realm is inspired by Apple’s NSPredicate. Let’s briefly summarize the supported features and syntax:
- The comparison operands can be property names or constants. At least one of the operands must be a property name. Special constants are false , true , and null .
- Timestamps can be specified in the formats YYYY-MM-DD@HH:MM:SS:NANOSECONDS and YYYY-MM-DDTHH:MM:SS:NANOSECONDS where nanoseconds can be omitted.
- The comparison operators = / == , , , >= , > , and != / <> are supported for int , float , double , and Date property types, e.g. age = 45 .
- The comparison operators = / == and != / <> are supported for boolean ( bool ) properties.
- For string and data ( ArrayBuffer ) properties, the = (and == ), != (and <> ), BEGINSWITH , CONTAINS , and ENDSWITH operators are supported, e.g. name CONTAINS ‘Ja’ .
- Wildcard comparison is possible for strings with the LIKE operator, e.g. name LIKE ‘*an?’ to match “Jane”, “Dan”, “Shane”, etc.
- Case-insensitive comparisons for strings using [c] , e.g. , CONTAINS[c] ‘Ja’ . Note that only characters “A-Z” and “a-z” will be ignored for case.
- Realm supports the following compound operators: AND / && , OR / || , and NOT / ! , e.g. name BEGINSWITH ‘J’ AND age >= 32 .
- The aggregate expressions @count / @size , @min , @max , @sum and @avg are supported on list properties, e.g. employees.@count > 5 to find list of employees with more than 5 elements.
- The aggregate expression @count / @size on strings and binary properties, e.g. name.@size = 5 to find all with a name of 5 letters.
- A key path can follow list properties relationships, e.g. child.age >= 13 and cars.@avg.milage > 1000 .
- A key path can also follow linking objects (backlinks), e.g. parents.age > 25 and parents.@count == 2 .
- The $ operator can be used to substitute arguments, e.g. child.age >= $0 (see the example below).
- Sorting and find distinct values are possible with functions SORT and DISTINCT , e.g. age > 20 SORT(name ASC, age DESC) DISTINCT(name) .
- The ordering for sorting can be one of the following case insensitive literals: ASC , ASCENDING , DESC , DESCENDING .
- Any number of properties can appear inside the brackets in a comma separated list.
- Any number of sort/distinct conditions can be indicated, they will be applied in the specified order.
- Sort or distinct cannot operate independently, these conditions must be attached to at least one query filter.
An non-trivial example on how to query a Realm is:
The output of the code snippet is:
Sorting
Results allows you to specify a sort criteria and order based on a single or multiple properties. For example, the following call sorts the returned cars from the example above numerically by miles:
Results can also be sorted on the values of objects linked to by the objects you’re sorting:
List s of basic types can be sorted by their values by calling sorted() without specifying a property:
Note that the order of Results is only guaranteed to stay consistent when the query is sorted. For performance reasons, insertion order is not guaranteed to be preserved.
Auto-Updating Results
Results instances are live, auto-updating views into the underlying data, which means results never have to be re-fetched. Modifying objects that affect the query will be reflected in the results immediately. The one exception to this is when using for. in or for. of , which will always iterate over the objects which matched the query when the iteration is started, even if some of them are deleted or modified to be excluded by the filter during the iteration.
This applies to all Results instances, included those returned by the objects , filtered , and sorted methods.
This property of Results not only keeps Realm fast and efficient, it allows your code to be simpler and more reactive. For example, if your view relies on the results of a query, you can store the Results in a property and access it without having to make sure to refresh its data prior to each access.
You can subscribe to notifications to know when Realm data is updated, indicating when your app’s UI should be refreshed for example, without having to re-fetch your Results .
Limiting Results
Most other database technologies provide the ability to вЂpaginate’ results from queries (such as the вЂLIMIT’ keyword in SQLite). This is often done out of necessity to avoid reading too much from disk, or pulling too many results into memory at once.
Since queries in Realm are lazy, performing this sort of paginating behavior isn’t necessary at all, as Realm will only load objects from the results of the query once they are explicitly accessed.
If for UI-related or other implementation reasons you require a specific subset of objects from a query, it’s as simple as taking the Results object, and reading out only the objects you need.
Migrations
When working with a database your data model will most likely change over time. For example, suppose we have the following Person model:
We want to update the data model to require a name property, rather than separate first and last names. To do this, we simply change the schema to the following:
At this point if you had saved any data with the previous model version there will be a mismatch between the new code and the old data Realm has stored on disk. When this occurs, an exception will be thrown when you try to open the existing Realm with the new schema unless you run a migration.
Performing a Migration
You define a migration and the associated schema version by updating the schemaVersion and defining an optional migration function. Your migration function provides any logic needed to convert data models from previous schemas to the new schema. When opening a Realm the migration function will be applied to update the Realm to the given schema version only if a migration is needed.
If no migration function is supplied then any new properties are automatically added and old properties are removed from the database when updating to the new schemaVersion . If you need to update old or populate new properties when upgrading your version you can do this in the migration function. For example, suppose we want to migrate the Person model declared earlier. You can populate the name property of the new schema using the old firstName and lastName properties:
Once the migration is successfully completed the Realm and all of its objects can be accessed as usual by your app.
Linear Migrations
With the migration pattern described above you can potentially run into issues when migrating over multiple versions. This could happen if a user skips an app update and a property has been changed multiple times in the versions being skipped. In this case you may need to edit old migration code to correctly update data from old schema to the latest schema.
It’s possible to avoid this issue by running multiple migrations sequentially, making sure that the database is upgraded to each previous version and that the associated migration code is run. When following this pattern old migration code should never have to be modified, although you will need to keep all old schema and migration blocks for future use. An example of what this would look like:
Notifications
The Realm , Results and List objects provide addListener methods to register notification callbacks. Whenever the object is updated, the change notification callback will be called.
There are two kinds of notifications, “Realm Notifications” (simple callbacks notified when write transactions are committed) and “Collection Notifications” (more sophisticated callbacks which receive change metadata on insertions, deletions and updates).
In some cases the listener may be called when the transaction starts—if the Realm is advanced to the latest version, or Realm entities being observed were modified or deleted in a way that triggers notifications. In those cases, the listener runs within the context of the current write transaction, so an attempt to begin a new write transaction within the notification handler will throw an exception. You can use the Realm.isInTransaction property to determine if your code is executing within a write transaction.
Realm Notifications
Realm instances send out notifications to other instances every time a write transaction is committed. To register for notifications:
Collection Notifications
Collection notifications contain information that describe what changes have occurred at a fine-grained level. This consists of the indices of objects that have been inserted, deleted, or modified since the last notification. Collection notifications are delivered asynchronously: first with the initial results, and then after any write transaction which modifies any of the objects in the collection, deletes objects from the collection, or adds new objects to the collection.
The notification callback function given to addListener receives two parameters when these changes occur. The first one is the collection that changed, and the second one is a changes object with information about the collection indices affected by deletions, insertions and modifications.
The former two, deletions and insertions, record the indices whenever objects start and stop being part of the collection. This takes into account when you add objects to the Realm or delete them from the Realm. For Results this also applies when you filter for specific values and the object was changed so that it is now matching the query or not matching anymore. For collections based on List , this applies when objects are added or removed from the relationship.
Your application is notified about modifications whenever a property of an object has changed, which was previously part of the collection and is still part of it. This happens as well when to-one and to-many relationships change, but doesn’t take changes on inverse relationships into account.
Let’s assume you’re observing a list of dog owners as given by the model code above. You will be notified about modifications for a matched Person object when:
- You modify the Person ’s name property.
- You add or remove a Dog to the Person ’s dogs property.
- You modify the age property of a Dog belonging to that Person .
This makes it possible to discretely control the animations and visual updates made to the content inside your UI, instead of arbitrarily reloading everything each time a notification occurs.
Working with a Synchronized Realm
Are you looking to use Realm Mobile Platform to synchronize all of your Realm Databases? All sync related documentation has been moved to our platform documentation
Encryption
Please take note of the Export Compliance section of our LICENSE, as it places restrictions against the usage of Realm if you are located in countries with an export restriction or embargo from the United States.
Realm supports encrypting the database file on disk with AES-256+SHA2 by supplying a 64-byte encryption key when creating a Realm.
This makes it so that all of the data stored on disk is transparently encrypted and decrypted with AES-256 as needed, and verified with a SHA-2 HMAC. The same encryption key must be supplied every time you obtain a Realm instance.
There is a small performance hit (typically less than 10% slower) when using encrypted Realms.
Examples
Examples can be found on GitHub in the realm-js repository.
Note that on Android, you need the NDK installed and must have set the ANDROID_NDK environment variable.
Troubleshooting
Missing Realm Constructor
If your app crashes, telling you that the Realm constructor was not found, there are a few things you can try:
First of all, run react-native link realm , but only if you’re using React Native MainApplication.java file:
And add the RealmReactPackage to the list of packages:
add following two lines in settings.gradle :
If your problem is on iOS, try:
- Close all simulators/device builds
- Stop the package manager running in terminal (or better yet, just restart terminal)
- Open the ios folder in your app root in finder
- Go into the build folder (note: you won’t see this build folder in atom, so just right click ios and click open in finder)
- Delete everything inside of the build folder (just move to trash and keep trash around in case you’re worried)
- Run react-native run-ios to rebuild the whole thing
Chrome Debugging is slow
We are aware of this. The reason for this is that since Realm is written in C++ and runs native code, it has to run on the device/simulator. But given the zero-copy architecture, we need to send values in realm objects over the RPC wire every time you inspect an object that is stored in a Realm.
We are investigating various potential solutions for this problem. If you want to keep track of it, you can follow the GitHub issue.
Cannot download realm-sync-cocoa
We have seen a few reports where users are not able to build their app due to download problems. The symptome is that you see an error message like Error: unexpected end of file at Zlib.zlibOnError [as onerror] (zlib.js:142:17) errno: -5, code: ‘Z_BUF_ERROR’ > .
It is possible to manually download the required files, and then build the app. The steps are:
- Locate to your project directory, and find node_modules/realm/vendor/realm-ios . It will be empty.
- Create the file download-realm.lock using the following command: echo SYNC_SERVER_FOLDER=sync SYNC_ARCHIVE=realm-sync-cocoa-3.7.0.tar.gz SYNC_ARCHIVE_ROOT=core > download-realm.lock . The version number (here 3.7.0) must match the Realm Sync version in the change log.
- Locate to your downloaded file realm-sync-cocoa-3.7.0.tar.gz excute this command tar -xzvf realm-sync-cocoa-3.7.0.tar.gz -C yourProjectDirectory/node_modules/realm/vendor/realm-ios .
- You will find the directory is not empty any more. Copy all the files under directory core and paste them under directory yourProjectDirectory/node_modules/realm/vendor/realm-ios .
Crash Reporting
We encourage you to use a crash reporter in your application. Many Realm operations could potentially fail at runtime (like any other disk IO), so collecting crash reports from your application will help identify areas where either you (or us) can improve error handling and fix crashing bugs.
Most commercial crash reporters have the option of collecting logs. We strongly encourage you to enable this feature. Realm logs metadata information (but no user data) when throwing exceptions and in irrecoverable situations, and these messages can help debug when things go wrong.
Источник