Over a million developers have joined DZone.

Realm by Example: CRUD on Android in 200 Lines of (Very Readable) Java

Introduction to Realm, a mobile database with an OO-optimized persistence engine.

· Mobile Zone

Nowadays working with databases is an integral part of programming. Android allows you to apply the database SQLite for storing information on devices. Standard ways of using it are uncomfortable. Working with SQLite sometimes makes code difficult to understand, and the writing of some SQL queries can take too much time. Using ORM partially solves some problems, but today we have an alternative way, known as Realm

Realm is a mobile database and a good substitute for SQLite (Android) & CoreData (iOS).

Prerequisites:

  • Realm is supported in Android only, not available for Java at the moment.
  • Android Studio version 0.8.6
  • JDK version 7
  • Android API Level minimum 9 (Android 2.3 Gingerbread)

Installation

Add compile 'io.realm:realm-android:0.83.0+' in your build.gradle and sync a project. Or, you can download a realm-VERSION.jar and add it into app/libs.

Models

If you want a class to be stored in Realm, it should extend from RealmObject.  Realm supports the following field types: boolean, byte, short, ìnt, long, float, double, String, Date. Moreover, subclasses of RealmObject and RealmList<? extends RealmObject> support model relationships.                                        
The boxed types Boolean, Byte, Short, Integer, Long, Float, and Double can also be used in model classes. With their help, you can set the value of a field to null.

Annotations

@Required - tells Realm to enforce checks that disallow null values. 
@Ignore  - supposes that a field should not be persisted to disk. 
@Index - will add a search index to the field. Due to this queries will be faster, although inserts will become slower and the data file will get larger.    
@PrimaryKey - supposes that the field is indexed. 

Start Using Realm

Initialize Realm in Application:

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    RealmConfiguration config = new RealmConfiguration.Builder(context).build();
    Realm.setDefaultConfiguration(config);
  }
}

Initialize Realm in Activity:

public class MyActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Realm realm = Realm.getDefaultInstance();
  }
}

Writing in the Database

If you want to write something in the database you just need to call:

Realm realm = Realm.getInstance(this);
realm.beginTransaction();
//... add or update objects here ...
realm.commitTransaction();

You always have an opportunity to cancel your transactions, just call:

realm.cancelTransaction();

Creating Objects

If you want to save an object in the Realm database, the class of that object should extend RealmObject:

public class University extends RealmObject {
    @Index
    private int id;
    private String name;
// Standard getters & setters generated by your IDE…
}
Realm realm = Realm.getInstance(this);
realm.beginTransaction();
University university = realm.createObject(University.class); // Create a new object
user.setName("John");
realm.commitTransaction();

Practical Use

Let’s see how this database can be applied to a real application. MLSDev developers made an Android app using Realm. You can find it in our repository to learn more about its integration. 

One of the app’s features is to add and delete universities, as well as add students to and delete them from these universities. This function is important for us in regards to the topic. In this article, we will show you only the main parts of the code.

So, two classes are required (University and Student):

public class Student extends RealmObject {
    @PrimaryKey  
    private String id;
    @Required    
    private String name;
    @Required    
    private Date birthday;
    @Required  
    private String email;
    // getters and setters
}
public class University extends RealmObject {
    @PrimaryKey
    private String id;
    @Required
    private String name;
    private RealmList students;
   // getters and setters
}

Then, create a class called "module" and include the University and Student classes in the annotation.

@RealmModule(classes = {Student.class, University.class})
public class SimpleRealmModule {}

In the Application class, initialize the Realm database using the previous class.

public class SimpleRealmApp extends Application {

    private static SimpleRealmApp instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        RealmConfiguration config = new RealmConfiguration.Builder(getApplicationContext()).setModules(new SimpleRealmModule()).build();
        Realm.setDefaultConfiguration(config);
    }

     public static SimpleRealmApp getInstance() {
        return instance;
    }
}

And, now it's time for the most interesting part. We will create two classes (UniversityRepository and StudentRepository) and write queries. 

UniversityRepository will be able to add a university, delete a university by id, get a university by id from the database, etc.

public class UniversityRepository implements IUniversityRepository {

    @Override
    public void addUniversity(University university, OnAddUniversityCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        realm.beginTransaction();
        University u = realm.createObject(University.class);
        u.setId(UUID.randomUUID().toString());
        u.setName(university.getName());
        realm.commitTransaction();

        if (callback != null)
            callback.onSuccess();
    }

    @Override
    public void deleteUniversityById(String Id, OnDeleteUniversityCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        realm.beginTransaction();
        University university = realm.where(University.class).equalTo(RealmTable.ID, Id).findFirst();
        university.removeFromRealm();
        realm.commitTransaction();

        if (callback != null)
            callback.onSuccess();
    }

    @Override
    public void deleteUniversityByPosition(int position, OnDeleteUniversityCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        realm.beginTransaction();
        RealmQuery query = realm.where(University.class);
        RealmResults results = query.findAll();
        results.remove(position);
        realm.commitTransaction();

        if (callback != null)
            callback.onSuccess();
    }

    @Override
    public void getUniversityById(String id, OnGetUniversityByIdCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        University result = realm.where(University.class).equalTo(RealmTable.ID, id).findFirst();

        if (callback != null)
            callback.onSuccess(result);
    }

    @Override
    public void getAllUniversities(OnGetAllUniversityCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        RealmQuery query = realm.where(University.class);
        RealmResults results = query.findAll();

        if (callback != null)
            callback.onSuccess(results);
    }

}  

The following screens display what you get from the code:

Image title

On the first screen, you can see the list of all universities. On the second screen, you can add a new university.

StudentRepository will be able to add a student to a university, delete a student by id, get a student by id from the database, etc.

public class StudentRepository implements IStudentRepository {

    @Override
    public void addStudent(Student student, OnSaveStudentCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        realm.beginTransaction();
        Student realmStudent = realm.createObject(Student.class);
        realmStudent.setId(UUID.randomUUID().toString());
        realmStudent.setName(student.getName());
        realmStudent.setBirthday(student.getBirthday());
        realmStudent.setEmail(student.getEmail());
        realm.commitTransaction();

        if (callback != null)
            callback.onSuccess();
    }

    @Override
    public void addStudentByUniversityId(Student student, String universityId, OnSaveStudentCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        realm.beginTransaction();

        Student realmStudent = realm.createObject(Student.class);
        realmStudent.setId(UUID.randomUUID().toString());
        realmStudent.setName(student.getName());
        realmStudent.setEmail(student.getEmail());
        realmStudent.setBirthday(student.getBirthday());

   University university = realm.where(University.class).equalTo(RealmTable.ID, universityId).findFirst();
        university.getStudents().add(realmStudent);

        realm.commitTransaction();

        if (callback != null)
            callback.onSuccess();

    }

    @Override
    public void deleteStudentById(String id, OnDeleteStudentCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        realm.beginTransaction();
        Student result = realm.where(Student.class).equalTo(RealmTable.ID, id).findFirst();
        result.removeFromRealm();
        realm.commitTransaction();

        if (callback != null)
            callback.onSuccess();
    }

    @Override
    public void deleteStudentByPosition(int position, OnDeleteStudentCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        realm.beginTransaction();
        RealmQuery query = realm.where(Student.class);
        RealmResults results = query.findAll();
        results.remove(position);
        realm.commitTransaction();

        if (callback != null)
            callback.onSuccess();
    }

    @Override
    public void getAllStudents(OnGetAllStudentsCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        RealmResults results = realm.where(Student.class).findAll();

        if (callback != null)
            callback.onSuccess(results);
    }

    @Override
    public void getAllStudentsByUniversityId(String id, OnGetStudentsCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        University university = realm.where(University.class).equalTo(RealmTable.ID, id).findFirst();
        RealmList students = university.getStudents();

        if (callback != null)
            callback.onSuccess(students);

    }

    @Override
    public void getStudentById(String id, OnGetStudentByIdCallback callback) {
        Realm realm = Realm.getInstance(SimpleRealmApp.getInstance());
        Student student = realm.where(Student.class).equalTo(RealmTable.ID, id).findFirst();

        if (callback != null)
            callback.onSuccess(student);
    }
}  

This is what you will see on the screens:

Image title

The first screen displays the list of all students of a chosen university. On the second one, you can add a new student.

As you might notice, it is very easy to write queries in Realm. Before each transaction, you should call: 

realm.beginTransaction(); 

And after it, you should call:

realm.commitTransaction();

You can also go to the official Realm website to learn more about queries.

Some Bad and Good Impressions of Working With Realm

Bad:

  • ID for objects cannot be automatically generated
  • You can have only getter and setter methods in a class. This means you cannot override the methods
hashcode();

or

equals();

Good:

  • An easy way to perform queries and transactions asynchronously.
  • All fetches (including queries) are lazy in Realm.  
  • An easy way to build queries (just call existing Realm methods).
  • Possibility to run the Realm database in-Memory.
  • Possibility to use Realm objects across threads.
  • More information is in the official documentation.

MLSDev Blog

Topics:
android ,realm ,sqlite ,mobile

Published at DZone with permission of Roman Kukhar, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}