Using Realm Database in Mobile Applications

Introduction

Realm is an Open Source mobile database, based on the ORM model and a replacement for SQLite. Realm does not use SQLite as its engine and instead it has its own C++ core. Realm stores data in a universal, table-based format by a C++ core. It is cross-platform, supporting Java (in Android only), Android 2.3 i.e. Gingerbread and above, Objective C, Swift, React Native, Xamarin.

Why Realm?

Realm is the fastest database today, with respect to performance, speed and efficiency. One should migrate to Realm because of its unique features:

1.  Zero Copy

Zero Copy means it does not copy results to the cursor window by getting a list of references to the matching objects and one can work directly work with the original objects.

2.  Auto Update UI

Objects in Realm are `live’ and  you don’t have to re-fetch them again.  It can be implemented through realm.addChangeListener

3.  Works on MVCC architecture

`Writes’ does not block `Read’ operations.  Thanks to MVCC architecture, i.e. Multi Version Concurrency Control, the Reader always reads another copy or version of data.

4. Uses a Fluent Interface

To construct multi-clause queries. E.g. Wealm.where(User.class).equalTo(“name”, “John”).or().equalTo(“name”, “Peter”).findAll();

5.  Faster read/writes

Up to 10x speed than SQLite for normal operations.

6.  No Mapping

Results do not need to be mapped to models.

7.  Ease of use

Easy to learn and understand

Installation

Installing Realm as a Gradle plugin requires two steps:

Add the following class path dependency to the project level build.gradle file.

dependencies {
 classpath "io.realm:realm-gradle-plugin:2.2.1"
 }

Apply the realm-android plugin to the top of application level build.gradle.

apply plugin: 'realm-android'

Config class file

Create a class which extends  the application and in it create `write’:

RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this)
 .name(Realm.DEFAULT_REALM_NAME)
 .schemaVersion(0)
 .deleteRealmIfMigrationNeeded()
 .build();
 Realm.setDefaultConfiguration(realmConfiguration);

Model class file

Create a model class file for Realm.  Unlike others, you need to use this model to create general Java objects too.

Supported field types are: Boolean, Byte, Short, Int, Long, Float, Double, String, Date and byte[].

Public, Private and Protected access specifiers are also supported.

public class User extends RealmObject {
 @PrimaryKey
 private String name;
 @Required
 private int age;
 @Ignore
 private int sessionId;
 @Index
 public String username

// Realm Model Class supports public, protected and private fields as well as custom methods.
// Standard getters & setters generated by your IDE…
}


Relationships

1. One to many

public class Contact extends RealmObject {
 private Email email;
 // Other fields…
 }

2.  Many to many:

public class Contact extends RealmObject {
 public String name;
 public RealmList<Email> emails;
 }

public class Email extends RealmObject {
public String address;
public boolean active;
}

Writes

All write operations (adding, modifying, and removing objects) must be wrapped in write transactions.

// Obtain a Realm instance
 Realm realm = Realm.getDefaultInstance();
 realm.beginTransaction();

//… add or update objects here …

realm.commitTransaction();
or
realm.cancelTransaction();

Creating objects

Every mutator (write, update, delete) operation should be written inside the transaction block.

Either create a new realm object by using User user =  realm.createObject(User.class); and then set data to it by user.setname(“john”) or set email and use the below code, so that you can insert user object with regard to Java or finally you can also copy it to Realm.

User user = new User("John");
 user.setEmail("john@corporation.com");

// Copy the object to Realm. Any further changes must happen on realmUser
realm.beginTransaction();
User realmUser = realm.copyToRealm(user);
realm.commitTransaction();

Queries

To find all users named John or Peter you would write:

No need of Transaction Blocks for queries. Objects can be accessed and queried at any time.

Realm results are ordered.Logical-And is Implicit, Logical-or must be applied explicitly with or().

Results in realm are Auto-updating. So you can provide notifications or update UI whenever realm.addChangeListener get the change.

RealmResults<User> result2 = realm.where(User.class)
 .equalTo("name", "John")
 .or()
 .equalTo("name", "Peter")
 .findAll();

This is a fluent interface most object oriented language uses to built multi-clause queries.

Deletion

// obtain the results of a query

final RealmResults<Dog> results = realm.where(Dog.class).findAll();

// All changes to data must happen in a transaction

realm.executeTransaction(new Realm.Transaction() {

@Override

public void execute(Realm realm) {

// remove single match

results.deleteFirstFromRealm();

results.deleteLastFromRealm();

// remove a single object

Dog dog = results.get(5);

dog.deleteFromRealm();

// Delete all matches

results.deleteAllFromRealm();

}

});

Limitations

Passing Instances across Threads (enforces transaction version isolation).

  1. Updating to newer versions is slightly difficult as several things change in newer versions
  2. There is no support for auto-incrementing field values like ID fields
  3. Not many learning resources are available

References

https://realm.io/docs

Author

  • Swarnim Dixit is a trainee Software Engineer with Trigent Software. He works as Android Application Developer. Swarnim enjoys developing innovative mobile apps and working on new technologies.