Realm and auto increment Behavior (Android)

22,023

Solution 1

Realm currently doesn't support auto incrementing primary keys. However you can easily implement it yourself using something like:

public int getNextKey() { 
    try { 
         Number number = realm.where(object).max("id");
         if (number != null) {
             return number.intValue() + 1;
         } else {
             return 0;
         }
    } catch (ArrayIndexOutOfBoundsException e) { 
         return 0;
    }
}

I hope that can get you started.

Solution 2

The Java binding does not support primary keys yet, but it's on the roadmap and with high priority - see: https://groups.google.com/forum/#!topic/realm-java/6hFqdyoH67w . As a workaround you can use this piece of code for generating keys:

int key;
try {
  key = realm.where(Child_pages.class).max("id").intValue() + 1;
} catch(ArrayIndexOutOfBoundsException ex) {
 key = 0;
}

I use singleton factory for generating primary keys as a more generic solution with better performance (no need to query for max("id") every time thanks to AtomicInteger).

There is a long discussion in Realm Git Hub if you need more context: Document how to set an auto increment id?

Solution 3

As already mentioned, auto-increment isn't supported yet.

But for those who use kotlin and wants to have an auto-increment behavior with realm, this is one of the possibilities:

open class Route(
    @PrimaryKey open var id: Long? = null,
    open var total: Double? = null,
    open var durationText: String? = null,
    open var durationMinutes: Double? = null,
    open var distanceText: String? = null,
    open var distanceMeters: Int? = null): RealmObject() {

companion object {
    @Ignore var cachedNextId:Long? = null
        get() {
            val nextId =    if (field!=null) field?.plus(1)
                            else Realm.getDefaultInstance()?.where(Route::class.java)?.max("id")?.toLong()?.plus(1) ?: 1
            Route.cachedNextId = nextId
            return nextId
        }
}}

Solution 4

Here is a genereic solution, personnaly I create a class named RealmUtils and I add this type of methods :

 public static int getPrimaryKey(Class c)
{
    Realm realm = Realm.getDefaultInstance();

    String primaryKeyFied = realm.getSchema().get(c.getSimpleName()).getPrimaryKey();
    if (realm.where(c).max(primaryKeyFied)== null)
        return 1;
    int value = realm.where(c).max(primaryKeyFied).intValue();
    return value+1;
}

Why I return 0 when the table is empty ? Because I hate Id's with 0 as value, so just change it. Hope it help someone.

Share:
22,023

Related videos on Youtube

Bachlet Tansime
Author by

Bachlet Tansime

Updated on July 09, 2022

Comments

  • Bachlet Tansime
    Bachlet Tansime almost 2 years

    I'm trying to get data from Realm using an ID as a reference. However, when querying for an ID, I've found that Realm is giving me the same ID for all elements (ID of 0). Why doesn't the ID auto-increment when I use the @PrimaryKey annotation on the model's ID?

    Here's the shortened class for the model:

    public class Child_pages extends RealmObject {
        @PrimaryKey
        private int id_cp;
    
        private int id;
        private String day;
        private int category_id;
    

    And the query I'm executing is: realm.where(Child_pages.class).equalTo("id_cp",page_id).findFirst()

    • Mast
      Mast about 9 years
      Could you please increase the readability of your post? What do you want to achieve and what's going wrong?
    • Bachlet Tansime
      Bachlet Tansime about 9 years
      It's clear that we get data using query specially ID of element, so my question is how I can get my objects from data base using ID and realm gives all the ID, the same value =0, why isn't auto Increment !
  • atabek
    atabek over 8 years
    As maximumInt method has been deprecated, now we need to use .max("id").intValue() instead.
  • beni
    beni over 8 years
    we need to add an try and catch for ArrayIndexOutOfBoundsException when the object is not created in the database. try { return realm.where(object).max("id").intValue() + 1; } catch (ArrayIndexOutOfBoundsException e) { return 0; }
  • David Miguel
    David Miguel over 7 years
    If there are no objects of that type in the db, max("id") returns null. So you have to check that before calling intValue(), and return the first id if it is null.
  • dakshbhatt21
    dakshbhatt21 over 7 years
    Above code works fine for me, but I got NPE for the first time instead of AIOOBE. BTW I used the long as primary key "id".
  • zacheusz
    zacheusz over 7 years
    this snippet is pretty old - what version of realm do you use?
  • dakshbhatt21
    dakshbhatt21 over 7 years
    I'm using 2.2.0
  • Neon Warge
    Neon Warge over 7 years
    Can someone explain to me the reason for this? Why is this thing not included out of the box?
  • EpicPandaForce
    EpicPandaForce almost 7 years
    @NeonWarge because autoincremented primary key doesn't work in distributed environment which is the Realm Sync
  • Farid
    Farid over 4 years
    I wonder when they will get to medium-priority issues if high-priority is in the waiting list for 4 years