New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how to set an auto increment id? #469

Closed
djyde opened this Issue Oct 12, 2014 · 47 comments

Comments

Projects
None yet
@djyde

djyde commented Oct 12, 2014

No description provided.

@bmunkholm

This comment has been minimized.

Show comment
Hide comment
@bmunkholm

bmunkholm Oct 12, 2014

Contributor

Hi Randy,
We currently don't support that, but plan to do so.
Until then, you would have to create a field yourself.
Could you please expand on your needs for it?

There was also some related discussion here:
https://groups.google.com/forum/#!topic/realm-java/6hFqdyoH67w

Thanks!

On Sun, Oct 12, 2014 at 9:55 AM, Randy notifications@github.com wrote:


Reply to this email directly or view it on GitHub
#469.

Contributor

bmunkholm commented Oct 12, 2014

Hi Randy,
We currently don't support that, but plan to do so.
Until then, you would have to create a field yourself.
Could you please expand on your needs for it?

There was also some related discussion here:
https://groups.google.com/forum/#!topic/realm-java/6hFqdyoH67w

Thanks!

On Sun, Oct 12, 2014 at 9:55 AM, Randy notifications@github.com wrote:


Reply to this email directly or view it on GitHub
#469.

@kneth kneth added the T:Enhancement label Oct 22, 2014

@mpost

This comment has been minimized.

Show comment
Hide comment
@mpost

mpost Jan 25, 2015

I would also be interested in an auto id feature. Maybe not even an increment but a UUID.

mpost commented Jan 25, 2015

I would also be interested in an auto id feature. Maybe not even an increment but a UUID.

@vuhung3990

This comment has been minimized.

Show comment
Hide comment
@vuhung3990

vuhung3990 Apr 9, 2015

i use this on android

                realm.beginTransaction();
                dbObj obj = realm.createObject(dbObj.class);

                // increatement index
                int nextID = (int) (realm.where(dbObj.class).maximumInt("id") + 1);

                // insert new value
                obj.setId(nextID);
                obj.setName("thang");
                obj.setAge(10);

                realm.commitTransaction();

id always max+1, but it isn't good solution

vuhung3990 commented Apr 9, 2015

i use this on android

                realm.beginTransaction();
                dbObj obj = realm.createObject(dbObj.class);

                // increatement index
                int nextID = (int) (realm.where(dbObj.class).maximumInt("id") + 1);

                // insert new value
                obj.setId(nextID);
                obj.setName("thang");
                obj.setAge(10);

                realm.commitTransaction();

id always max+1, but it isn't good solution

@cmelchior cmelchior added P1 and removed P1 labels Apr 15, 2015

@bmunkholm bmunkholm added T:Doc and removed T:Enhancement labels May 6, 2015

@timanglade timanglade added P2 and removed backlog labels May 6, 2015

@rajuashok

This comment has been minimized.

Show comment
Hide comment
@rajuashok

rajuashok Jun 9, 2015

When I build a Messaging application I would like to create local fake message(s) with unique IDs and then update them with the actual unique key I get from the server after successful post. The way I do this in SQL is by setting an int id field to Primary Key and then setting String uniqueKey as part of my Unique Key. I've just started experimenting with Realm today, but some of these limitations have really made it difficult for me to migrate to Realm.

rajuashok commented Jun 9, 2015

When I build a Messaging application I would like to create local fake message(s) with unique IDs and then update them with the actual unique key I get from the server after successful post. The way I do this in SQL is by setting an int id field to Primary Key and then setting String uniqueKey as part of my Unique Key. I've just started experimenting with Realm today, but some of these limitations have really made it difficult for me to migrate to Realm.

@markini

This comment has been minimized.

Show comment
Hide comment
@markini

markini Aug 20, 2015

I have a lot of local models which needs an unique identifier.
I pass the id to fragments and threads and fetch them then from realm.

I'm doing something like this for now: model.setId(UUID.randomUUID().toString());
I'm still not sure what I should do when a collision occurs.

  • Overriding is no option in my case
  • Letting the app crash could lead to unpredictable states.

I'm thinking about either query every id before adding the model to realm or implement a rollback strategy (not sure how, or if possible).
Has anyone similar use cases?

markini commented Aug 20, 2015

I have a lot of local models which needs an unique identifier.
I pass the id to fragments and threads and fetch them then from realm.

I'm doing something like this for now: model.setId(UUID.randomUUID().toString());
I'm still not sure what I should do when a collision occurs.

  • Overriding is no option in my case
  • Letting the app crash could lead to unpredictable states.

I'm thinking about either query every id before adding the model to realm or implement a rollback strategy (not sure how, or if possible).
Has anyone similar use cases?

@hajoxx

This comment has been minimized.

Show comment
Hide comment
@hajoxx

hajoxx Sep 5, 2015

@markini Collision of UUID is very little chance.

hajoxx commented Sep 5, 2015

@markini Collision of UUID is very little chance.

@markini

This comment has been minimized.

Show comment
Hide comment
@markini

markini Sep 5, 2015

@Rexota yeah, we decided to just go without collision detection.
I looked a little bit into the UUID documentation and I guess collisions of said ids are indeed the least of my worries.

markini commented Sep 5, 2015

@Rexota yeah, we decided to just go without collision detection.
I looked a little bit into the UUID documentation and I guess collisions of said ids are indeed the least of my worries.

@AlokBansal8

This comment has been minimized.

Show comment
Hide comment
@AlokBansal8

AlokBansal8 Feb 2, 2016

@bmunkholm any update on it?

AlokBansal8 commented Feb 2, 2016

@bmunkholm any update on it?

@Arthez

This comment has been minimized.

Show comment
Hide comment
@Arthez

Arthez Feb 11, 2016

I to solve this issue with timestamp. What you do think about this? Int(NSDate().timeIntervalSince1970)

@ronanrodrigo Im afraid that this is bad way, I insert list of 8 and pairs of 3 have same ID (I use getNanos, miliseconds doesnt work for sure)

Arthez commented Feb 11, 2016

I to solve this issue with timestamp. What you do think about this? Int(NSDate().timeIntervalSince1970)

@ronanrodrigo Im afraid that this is bad way, I insert list of 8 and pairs of 3 have same ID (I use getNanos, miliseconds doesnt work for sure)

@cmelchior

This comment has been minimized.

Show comment
Hide comment
@cmelchior

cmelchior Feb 11, 2016

Contributor

Timestamps could work, but they only have millisecond precision which means that there is a small chance of two timestamps being created at the same time. Using an AtomicInteger would be safer:

e.g.

// Find max value when opening the DB
RealmConfiguration config = new RealmConfiguration.Builder(context).build();
Realm realm = Realm.getInstance(config);
AtomicLong primaryKeyValue = realm.where(Foo.class).max("id").longValue();
realm.close();

// ....

// Create new object
new Foo(primaryKeyValue.incrementAndGet());
Contributor

cmelchior commented Feb 11, 2016

Timestamps could work, but they only have millisecond precision which means that there is a small chance of two timestamps being created at the same time. Using an AtomicInteger would be safer:

e.g.

// Find max value when opening the DB
RealmConfiguration config = new RealmConfiguration.Builder(context).build();
Realm realm = Realm.getInstance(config);
AtomicLong primaryKeyValue = realm.where(Foo.class).max("id").longValue();
realm.close();

// ....

// Create new object
new Foo(primaryKeyValue.incrementAndGet());
@Arthez

This comment has been minimized.

Show comment
Hide comment
@Arthez

Arthez Feb 11, 2016

For now, I use something like this (For inserting List of RealmObjects):

int listSize = list.size();
for (int index = 0; index < listSize; index++) {
     list.get(index).setId(setUniqueId() + index);
}
// insert List to database

public static long setUniqueId() {
        Number num = realm.where(RealmObject.class).max(COLUMN_ID_NAME);
        if (num == null) return 1;
        else return ((long) num + 1);
    }

Miliseconds as id fail me because I get same id for 3 objects. My temp method lower performance quite a bit, inserting Lists of 8x RealmObjects (object has: long, String, String, int), 5000 times without uniqueId on average takes 3.755sec, with 5.312sec, but every next insertion (when database increase by 5000x8 objects) it adds up about 6.5sec every time, due to checking max id in the database.

EDIT: this can be done better, just save maxId in onCreate and then use it till you are done with Realm, and when you wanna use Realm again just get maxId again, not every time like in code above.

Arthez commented Feb 11, 2016

For now, I use something like this (For inserting List of RealmObjects):

int listSize = list.size();
for (int index = 0; index < listSize; index++) {
     list.get(index).setId(setUniqueId() + index);
}
// insert List to database

public static long setUniqueId() {
        Number num = realm.where(RealmObject.class).max(COLUMN_ID_NAME);
        if (num == null) return 1;
        else return ((long) num + 1);
    }

Miliseconds as id fail me because I get same id for 3 objects. My temp method lower performance quite a bit, inserting Lists of 8x RealmObjects (object has: long, String, String, int), 5000 times without uniqueId on average takes 3.755sec, with 5.312sec, but every next insertion (when database increase by 5000x8 objects) it adds up about 6.5sec every time, due to checking max id in the database.

EDIT: this can be done better, just save maxId in onCreate and then use it till you are done with Realm, and when you wanna use Realm again just get maxId again, not every time like in code above.

@cmelchior

This comment has been minimized.

Show comment
Hide comment
@cmelchior

cmelchior Feb 11, 2016

Contributor

You don't have to run that query every time, just once when the app start:

public class MyApplication extends Application {

  public static AtomicLong primaryKeyValue;

  public void onCreate() {
    RealmConfiguration config = new RealmConfiguration.Builder(context).build();
    Realm realm = Realm.getInstance(config);
    primaryKeyValue = new AtomicLong(realm.where(Foo.class).max("id").longValue());
    realm.close();
  }
}

public class MyActivity extends Activity {

  protected void onCreate() {
    long nextKey = MyApplication.primaryKeyValue.incrementAndGet();
  }
}

I would probably encapsulate it in something like a PrimaryKeyFactory class, but I hope the idea is clear. Just get the maximum key when starting the app, and then it is super cheap to generate the next value with an AtomicLong

Contributor

cmelchior commented Feb 11, 2016

You don't have to run that query every time, just once when the app start:

public class MyApplication extends Application {

  public static AtomicLong primaryKeyValue;

  public void onCreate() {
    RealmConfiguration config = new RealmConfiguration.Builder(context).build();
    Realm realm = Realm.getInstance(config);
    primaryKeyValue = new AtomicLong(realm.where(Foo.class).max("id").longValue());
    realm.close();
  }
}

public class MyActivity extends Activity {

  protected void onCreate() {
    long nextKey = MyApplication.primaryKeyValue.incrementAndGet();
  }
}

I would probably encapsulate it in something like a PrimaryKeyFactory class, but I hope the idea is clear. Just get the maximum key when starting the app, and then it is super cheap to generate the next value with an AtomicLong

@AlokBansal8

This comment has been minimized.

Show comment
Hide comment
@AlokBansal8

AlokBansal8 Feb 16, 2016

@cmelchior great work around. 👍
But would love to have annotation like @AutoIncrement which I can use in my RealmObjects.

AlokBansal8 commented Feb 16, 2016

@cmelchior great work around. 👍
But would love to have annotation like @AutoIncrement which I can use in my RealmObjects.

@fawaad

This comment has been minimized.

Show comment
Hide comment
@fawaad

fawaad Feb 22, 2016

@cmelchior, I think this is a good workaround as well. The problem lies in usage in an app that uses multiple Model classes. The Application's onCreate() could get very bloated fairly quickly.

This is something usually handled below the surface in most databases (I'm thinking MySQL and SQLite). Is this something you guys are trying to target for the official 1.0.0 release?

fawaad commented Feb 22, 2016

@cmelchior, I think this is a good workaround as well. The problem lies in usage in an app that uses multiple Model classes. The Application's onCreate() could get very bloated fairly quickly.

This is something usually handled below the surface in most databases (I'm thinking MySQL and SQLite). Is this something you guys are trying to target for the official 1.0.0 release?

@MichaelObi

This comment has been minimized.

Show comment
Hide comment
@MichaelObi

MichaelObi Mar 4, 2016

@fawaad I think the next release that's due (hopefully) next week should address this.

MichaelObi commented Mar 4, 2016

@fawaad I think the next release that's due (hopefully) next week should address this.

@joxad

This comment has been minimized.

Show comment
Hide comment
@joxad

joxad Mar 9, 2016

I just migrate from Active Android to Realm because I saw a lot of people talking about this lib, as far as I want to test Reactive as well. But the lack of AutoIncrement is very hard.
I 'll try the workaround for a time
RealmConfiguration config = new RealmConfiguration.Builder(context).build();
Realm realm = Realm.getInstance(config);
AtomicLong primaryKeyValue = realm.where(Foo.class).max("id").longValue();
realm.close();

// ....

// Create new object
new Foo(primaryKeyValue.incrementAndGet());

But It will be great to have this method done each time we make a new XXXRealmObject .

joxad commented Mar 9, 2016

I just migrate from Active Android to Realm because I saw a lot of people talking about this lib, as far as I want to test Reactive as well. But the lack of AutoIncrement is very hard.
I 'll try the workaround for a time
RealmConfiguration config = new RealmConfiguration.Builder(context).build();
Realm realm = Realm.getInstance(config);
AtomicLong primaryKeyValue = realm.where(Foo.class).max("id").longValue();
realm.close();

// ....

// Create new object
new Foo(primaryKeyValue.incrementAndGet());

But It will be great to have this method done each time we make a new XXXRealmObject .

@cmelchior

This comment has been minimized.

Show comment
Hide comment
@cmelchior

cmelchior Mar 15, 2016

Contributor

Until we can implement support for auto-generating primary keys in the bindings we should document the work-arounds. There is 4 cases:

  1. The data contains natural keys, e.g JSON with some kind of identifier -> Just add @PrimaryKey to that field in the Realm Model

  2. We just need a unique identifier in order to identify the object. UUID.randomUUID().toString() should be used either in the constructor if creating un-managed objects or through a setId(UUID) method if using realm.createObject().

  3. Be able to sort by insertion. Just add a createdAt = new Date() field.

  4. Need an unique identifier that is sortable: This is probably the most tricky one as timestamps are easily sortable but not guaranteed to be unique. In that case something like #469 (comment) probably wrapped in nice helper class like PrimaryKeyFactory or similar. We are just about to implement getPrimaryKey for RealmObjectSchema, once that is done we could actually create a nice drop-in helper class for this as we could dynamically determine the primary key field on startup.

Something like:


public class PrimaryKeyFactory {

    private static Map<Class, AtomicLong> keys = new HashMap<Class, AtomicLong>();

    public static void initialize(Realm realm) {
        // 1. Loop through all classes using RealmSchema / RealmObjectSchema / RealmConfiguration.getRealmObjectClassees()
        // 2. Determine the maximum value for each primary key field and save it in the `keys` map.
    }

    // Automitically create next key
    public synchronized long nextKey(Class clazz) {
        return keys.get(clazz).incrementAndGet();
    }
}
Contributor

cmelchior commented Mar 15, 2016

Until we can implement support for auto-generating primary keys in the bindings we should document the work-arounds. There is 4 cases:

  1. The data contains natural keys, e.g JSON with some kind of identifier -> Just add @PrimaryKey to that field in the Realm Model

  2. We just need a unique identifier in order to identify the object. UUID.randomUUID().toString() should be used either in the constructor if creating un-managed objects or through a setId(UUID) method if using realm.createObject().

  3. Be able to sort by insertion. Just add a createdAt = new Date() field.

  4. Need an unique identifier that is sortable: This is probably the most tricky one as timestamps are easily sortable but not guaranteed to be unique. In that case something like #469 (comment) probably wrapped in nice helper class like PrimaryKeyFactory or similar. We are just about to implement getPrimaryKey for RealmObjectSchema, once that is done we could actually create a nice drop-in helper class for this as we could dynamically determine the primary key field on startup.

Something like:


public class PrimaryKeyFactory {

    private static Map<Class, AtomicLong> keys = new HashMap<Class, AtomicLong>();

    public static void initialize(Realm realm) {
        // 1. Loop through all classes using RealmSchema / RealmObjectSchema / RealmConfiguration.getRealmObjectClassees()
        // 2. Determine the maximum value for each primary key field and save it in the `keys` map.
    }

    // Automitically create next key
    public synchronized long nextKey(Class clazz) {
        return keys.get(clazz).incrementAndGet();
    }
}

@bmunkholm bmunkholm changed the title from how to set an auto increment id? to Document how to set an auto increment id? Mar 15, 2016

@zacheusz

This comment has been minimized.

Show comment
Hide comment
@zacheusz

zacheusz Mar 17, 2016

this is what I use (based on @cmelchior concept):

import android.util.Log;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmObject;
import io.realm.RealmObjectSchema;
import io.realm.RealmSchema;
import static java.lang.String.format;

/**
 * Created by zacheusz on 16/03/16.
 * https://github.com/realm/realm-java/issues/469#issuecomment-196798253
 */
public class PrimaryKeyFactory {

   /** primary key field name */
    private static final String PRIMARY_KEY_FIELD = "id";

    /**
     * Singleton instance.
     */
    private final static PrimaryKeyFactory instance = new PrimaryKeyFactory();

    /**
     * Maximum primary key values.
     */
    private Map<Class<? extends RealmObject>, AtomicLong> keys;

    /**
     * get the singleton instance
     * @return singleton instance
     */
    public static PrimaryKeyFactory getInstance() {
        return instance;
    }

    /**
     * Initialize the factory. Must be called before any primary key is generated
    * - preferably from application class.
    */
    public synchronized void initialize(final Realm realm) {
        if (keys != null) {
            throw new IllegalStateException("already initialized");
        }
        // keys field is used as an initialization flag at the same time
        keys = new HashMap<>();
        final RealmConfiguration configuration = realm.getConfiguration();
        final RealmSchema realmSchema = realm.getSchema();
        //using RealmConfiguration#getRealmObjectClasses because
        // RealmSchema#getAll() returns RealmObjectSchema with simple class names only
        for (final Class<? extends RealmObject> c : configuration.getRealmObjectClasses()) {

            final RealmObjectSchema objectSchema = realmSchema.get(c.getSimpleName());
            Log.i(getClass().getSimpleName(), format("schema for class %s : %s", c.getName(), objectSchema));
            if (objectSchema != null && objectSchema.hasPrimaryKey()) {
                Number keyValue = null;
                try {
                    keyValue = realm.where(c).max(PRIMARY_KEY_FIELD);
                } catch (ArrayIndexOutOfBoundsException ex) {
                    Log.d(getClass().getSimpleName(), format("error while getting number primary key %s " +
                            " for %s",PRIMARY_KEY_FIELD, c.getName()), ex);
                }
                if (keyValue == null) {
                    Log.w(getClass().getSimpleName(), format("can't find number primary key %s " +
                            " for %s.",PRIMARY_KEY_FIELD, c.getName()));
                } else {
                    keys.put(c, new AtomicLong(keyValue.longValue()));
                }
            }
        }
    }

    /**
     *  Automatically create next key for a given class.
     */
    public synchronized long nextKey(final Class<? extends RealmObject> clazz) {
        if (keys == null) {
            throw new IllegalStateException("not initialized yet");
        }
        AtomicLong l = keys.get(clazz);
        if (l == null) {
            Log.i(getClass().getSimpleName(), "There was no primary keys for " + clazz.getName());
            //RealmConfiguration#getRealmObjectClasses() returns only classes with existing instances
            //so we need to store value for the first instance created
            l = new AtomicLong(0);
            keys.put(clazz, l);
        }
        return l.incrementAndGet();
    }
}

Gist URL: https://gist.github.com/zacheusz/66c79df90b22a581d6f0

zacheusz commented Mar 17, 2016

this is what I use (based on @cmelchior concept):

import android.util.Log;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmObject;
import io.realm.RealmObjectSchema;
import io.realm.RealmSchema;
import static java.lang.String.format;

/**
 * Created by zacheusz on 16/03/16.
 * https://github.com/realm/realm-java/issues/469#issuecomment-196798253
 */
public class PrimaryKeyFactory {

   /** primary key field name */
    private static final String PRIMARY_KEY_FIELD = "id";

    /**
     * Singleton instance.
     */
    private final static PrimaryKeyFactory instance = new PrimaryKeyFactory();

    /**
     * Maximum primary key values.
     */
    private Map<Class<? extends RealmObject>, AtomicLong> keys;

    /**
     * get the singleton instance
     * @return singleton instance
     */
    public static PrimaryKeyFactory getInstance() {
        return instance;
    }

    /**
     * Initialize the factory. Must be called before any primary key is generated
    * - preferably from application class.
    */
    public synchronized void initialize(final Realm realm) {
        if (keys != null) {
            throw new IllegalStateException("already initialized");
        }
        // keys field is used as an initialization flag at the same time
        keys = new HashMap<>();
        final RealmConfiguration configuration = realm.getConfiguration();
        final RealmSchema realmSchema = realm.getSchema();
        //using RealmConfiguration#getRealmObjectClasses because
        // RealmSchema#getAll() returns RealmObjectSchema with simple class names only
        for (final Class<? extends RealmObject> c : configuration.getRealmObjectClasses()) {

            final RealmObjectSchema objectSchema = realmSchema.get(c.getSimpleName());
            Log.i(getClass().getSimpleName(), format("schema for class %s : %s", c.getName(), objectSchema));
            if (objectSchema != null && objectSchema.hasPrimaryKey()) {
                Number keyValue = null;
                try {
                    keyValue = realm.where(c).max(PRIMARY_KEY_FIELD);
                } catch (ArrayIndexOutOfBoundsException ex) {
                    Log.d(getClass().getSimpleName(), format("error while getting number primary key %s " +
                            " for %s",PRIMARY_KEY_FIELD, c.getName()), ex);
                }
                if (keyValue == null) {
                    Log.w(getClass().getSimpleName(), format("can't find number primary key %s " +
                            " for %s.",PRIMARY_KEY_FIELD, c.getName()));
                } else {
                    keys.put(c, new AtomicLong(keyValue.longValue()));
                }
            }
        }
    }

    /**
     *  Automatically create next key for a given class.
     */
    public synchronized long nextKey(final Class<? extends RealmObject> clazz) {
        if (keys == null) {
            throw new IllegalStateException("not initialized yet");
        }
        AtomicLong l = keys.get(clazz);
        if (l == null) {
            Log.i(getClass().getSimpleName(), "There was no primary keys for " + clazz.getName());
            //RealmConfiguration#getRealmObjectClasses() returns only classes with existing instances
            //so we need to store value for the first instance created
            l = new AtomicLong(0);
            keys.put(clazz, l);
        }
        return l.incrementAndGet();
    }
}

Gist URL: https://gist.github.com/zacheusz/66c79df90b22a581d6f0

@rsd-raul

This comment has been minimized.

Show comment
Hide comment
@rsd-raul

rsd-raul Mar 23, 2016

Wouldn't be better to have a global unique identifier instead of multiple object-dependant unique identifiers??

I mean, if you have multiple Model classes you will need to go though all of them any way, so you could just take the biggest one and be done with it... Not having to store a Map or use a Class as parameter in nextKey.

Something like:

public class PrimaryKeyFactory {

    // Model classes
    private static Class[] model = {ABCD.class, BCDA.class, CDAB.class, DABC.class};
    private static AtomicLong unique;

    public static void initialize(Realm realm) {
        // If unique already calculated, skip
        if (unique != null)
            return;

        // Start the DB in id = 2, id = 1 is in use...???
        unique = new AtomicLong(1);

        // Loop through all classes and determine the global maximum value
        for (Class clazz : model) {
            Number num = realm.where(clazz).max("id");

            // If there are no ids, skip
            if(num != null) {
                AtomicLong maxKey = new AtomicLong(num.longValue());
                if (maxKey.longValue() > unique.longValue())
                    unique = maxKey;
            }
        }
    }

    // Automatically create next key
    public static long nextKey() {
        return unique.incrementAndGet();
    }
}

This way I can call initialize once or as many times as I deem and only do the calculations once.

Is there something I'm missing with this approach?? Is the best solution I have think of.

Ps: I allow calling initialize multiple times as I don't plan to use it onCreate

rsd-raul commented Mar 23, 2016

Wouldn't be better to have a global unique identifier instead of multiple object-dependant unique identifiers??

I mean, if you have multiple Model classes you will need to go though all of them any way, so you could just take the biggest one and be done with it... Not having to store a Map or use a Class as parameter in nextKey.

Something like:

public class PrimaryKeyFactory {

    // Model classes
    private static Class[] model = {ABCD.class, BCDA.class, CDAB.class, DABC.class};
    private static AtomicLong unique;

    public static void initialize(Realm realm) {
        // If unique already calculated, skip
        if (unique != null)
            return;

        // Start the DB in id = 2, id = 1 is in use...???
        unique = new AtomicLong(1);

        // Loop through all classes and determine the global maximum value
        for (Class clazz : model) {
            Number num = realm.where(clazz).max("id");

            // If there are no ids, skip
            if(num != null) {
                AtomicLong maxKey = new AtomicLong(num.longValue());
                if (maxKey.longValue() > unique.longValue())
                    unique = maxKey;
            }
        }
    }

    // Automatically create next key
    public static long nextKey() {
        return unique.incrementAndGet();
    }
}

This way I can call initialize once or as many times as I deem and only do the calculations once.

Is there something I'm missing with this approach?? Is the best solution I have think of.

Ps: I allow calling initialize multiple times as I don't plan to use it onCreate

@behelit

This comment has been minimized.

Show comment
Hide comment
@behelit

behelit Apr 5, 2016

@cmelchior

AtomicLong primaryKeyValue = realm.where(Foo.class).max("id").longValue();

Hmm, compiler complains that longValue doesn't return an AtomicLong, also this causes a NullPointerException when there are no records.?

behelit commented Apr 5, 2016

@cmelchior

AtomicLong primaryKeyValue = realm.where(Foo.class).max("id").longValue();

Hmm, compiler complains that longValue doesn't return an AtomicLong, also this causes a NullPointerException when there are no records.?

@cmelchior

This comment has been minimized.

Show comment
Hide comment
@cmelchior

cmelchior Apr 5, 2016

Contributor

@behelit
Yes, that was just bad pseudo code.

Something like the below should be better:

AtomicLong primaryKeyValue; 

public void inititialize() {
  Number currentMax = realm.where(Foo.class).max("id");
  long nextId = 0
  if (currentMax != null) {
    nextId = currentMax.longValue() + 1;
  }
  primaryKeyValue = new AtomicLong(nextId);
}

public long getNextId() {
  return primaryKeyValue.getAndIncrement();
}
Contributor

cmelchior commented Apr 5, 2016

@behelit
Yes, that was just bad pseudo code.

Something like the below should be better:

AtomicLong primaryKeyValue; 

public void inititialize() {
  Number currentMax = realm.where(Foo.class).max("id");
  long nextId = 0
  if (currentMax != null) {
    nextId = currentMax.longValue() + 1;
  }
  primaryKeyValue = new AtomicLong(nextId);
}

public long getNextId() {
  return primaryKeyValue.getAndIncrement();
}
@zacheusz

This comment has been minimized.

Show comment
Hide comment
@zacheusz

zacheusz Apr 5, 2016

@cmelchior @behelit I would advise catching ArrayIndexOutOfBoundsException here - look at my code above.

zacheusz commented Apr 5, 2016

@cmelchior @behelit I would advise catching ArrayIndexOutOfBoundsException here - look at my code above.

@zacheusz

This comment has been minimized.

Show comment
Hide comment
@zacheusz

zacheusz Apr 5, 2016

@rsd-raul with your code:

  1. you will not have continuous PKs for particular table (class)
  2. you have to modify PrimaryKeyFactory each time you add a new model class
  3. catch ArrayIndexOutOfBoundsException from realm.where(clazz).max("id") - will be thrown for empty table

zacheusz commented Apr 5, 2016

@rsd-raul with your code:

  1. you will not have continuous PKs for particular table (class)
  2. you have to modify PrimaryKeyFactory each time you add a new model class
  3. catch ArrayIndexOutOfBoundsException from realm.where(clazz).max("id") - will be thrown for empty table
@rsd-raul

This comment has been minimized.

Show comment
Hide comment
@rsd-raul

rsd-raul Apr 5, 2016

@zacheusz

1- I'm not particularly worried about the continuous PKs as the most I need of them is to be correlative (order by "id") and I'm used to universal PKs.

eg: 1, 82, 23, 45 will be ordered 1, 23, 45 and 82 despite not being continuous, that should do the job for establishing a timeline for a model class.

2- Indeed, I've looked trough your previous answer and I've updated the model declaration to:

// Retrieve the model
Set<Class<? extends RealmObject>> model = realm.getConfiguration().getRealmObjectClasses();

Much much better now, thanks.

3- In my case I'm using realm 0.88.2, and the output for an empty table is null, which I test for in the model loop, lucky enough I don't have to catch the exception.

rsd-raul commented Apr 5, 2016

@zacheusz

1- I'm not particularly worried about the continuous PKs as the most I need of them is to be correlative (order by "id") and I'm used to universal PKs.

eg: 1, 82, 23, 45 will be ordered 1, 23, 45 and 82 despite not being continuous, that should do the job for establishing a timeline for a model class.

2- Indeed, I've looked trough your previous answer and I've updated the model declaration to:

// Retrieve the model
Set<Class<? extends RealmObject>> model = realm.getConfiguration().getRealmObjectClasses();

Much much better now, thanks.

3- In my case I'm using realm 0.88.2, and the output for an empty table is null, which I test for in the model loop, lucky enough I don't have to catch the exception.

@RaghavThakkar

This comment has been minimized.

Show comment
Hide comment

RaghavThakkar commented Jun 10, 2016

Here the updated PrimaryKeyFactory class
https://gist.github.com/RaghavThakkar/87027cb272804d2dc1fdde253c77ac90

@carloseduardosx

This comment has been minimized.

Show comment
Hide comment
@carloseduardosx

carloseduardosx Jun 15, 2016

I was create a implementation of Auto Increment feature for each Model from Realm Database
See: Sample of how to use RealAutoIncrement. Is pretty simple 😄

https://gist.github.com/carloseduardosx/a7bd88d7337660cd10a2c5dcc580ebd0

carloseduardosx commented Jun 15, 2016

I was create a implementation of Auto Increment feature for each Model from Realm Database
See: Sample of how to use RealAutoIncrement. Is pretty simple 😄

https://gist.github.com/carloseduardosx/a7bd88d7337660cd10a2c5dcc580ebd0

@daolq

This comment has been minimized.

Show comment
Hide comment
@daolq

daolq commented Jul 4, 2016

@carloseduardosx
Thank you!
I mix your suggest to resolve this problem:

https://gist.github.com/at-daolq/dfe77581294fd070eba0ad7369ce0c89

@carloseduardosx

This comment has been minimized.

Show comment
Hide comment
@carloseduardosx

carloseduardosx Sep 3, 2016

I was update the implementation of Auto Increment feature for Realm. Now is much more robust with support for large operations of insert and delete at same time. Everyone can see the new implementation here:

https://gist.github.com/carloseduardosx/6c3a3dfc3a9cb467aa464884f39544c2

See: Sample of how to use RealAutoIncrement. Is pretty simple too 😄

carloseduardosx commented Sep 3, 2016

I was update the implementation of Auto Increment feature for Realm. Now is much more robust with support for large operations of insert and delete at same time. Everyone can see the new implementation here:

https://gist.github.com/carloseduardosx/6c3a3dfc3a9cb467aa464884f39544c2

See: Sample of how to use RealAutoIncrement. Is pretty simple too 😄

@kejith

This comment has been minimized.

Show comment
Hide comment
@kejith

kejith Oct 21, 2016

I just wanted to share my attempt on solving this Problem, because i don't want to pass a primary Key value all the time. First i created a Database-Class to handle the storage of a RealmObject.

public class RealmDatabase {
Realm realm;

public RealmDatabase() {
    RealmConfiguration realmConfiguration =  new RealmConfiguration.Builder()
            .name("test").schemaVersion(1).build();

    try {
        realm = Realm.getInstance(realmConfiguration);
    } catch (Exception e) {
        Log.e("Realm init failed", e.getMessage());
    }
}

protected void saveObjectIntoDatabase(final RealmObject object) {
    realm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm bgRealm) {
            bgRealm.copyToRealm(object);    
        }
    }, new Realm.Transaction.OnSuccess() {
        @Override
        public void onSuccess() {
            // onSuccess
        }
    }, new Realm.Transaction.OnError() {
        @Override
        public void onError(Throwable error) {
            // onError
        }
    });
}

After creating the database-class i created an Interface to distinguish between Objects with a Primary Key and without.

public interface AutoIncrementable {
    public void setPrimaryKey(int primaryKey);
    public int getNextPrimaryKey(Realm realm);
}

Now you will just need to edit this code of the previous execute method

public void execute(Realm bgRealm) {
                if(object instanceof AutoIncrementable){
                    AutoIncrementable autoIncrementable = (AutoIncrementable) object;
                    autoIncrementable.setPrimaryKey(autoIncrementable.getNextPrimaryKey(bgRealm));
                    bgRealm.copyToRealm((RealmObject)autoIncrementable);
                } else {
                    bgRealm.copyToRealm(object);
                }
}

With this solution the database logic will still be in one class and this class can passed down to every class which needs to write into the database.

public class Person extends RealmObject implements AutoIncrementable{

    @PrimaryKey
    public int id;
    public String name;

    @Override
    public void setPrimaryKey(int primaryKey) {
        this.id = primaryKey;
    }

    @Override
    public int getNextPrimaryKey(Realm realm) {
        return realm.where(Person.class).max("id").intValue() + 1;
    }
}

Please give me some feedback. I am new to Realm and i thought it would be a good idea to handle it like this because i dont need to handle the primary key anymore because i only need to know the primary key when inserting into the database.

kejith commented Oct 21, 2016

I just wanted to share my attempt on solving this Problem, because i don't want to pass a primary Key value all the time. First i created a Database-Class to handle the storage of a RealmObject.

public class RealmDatabase {
Realm realm;

public RealmDatabase() {
    RealmConfiguration realmConfiguration =  new RealmConfiguration.Builder()
            .name("test").schemaVersion(1).build();

    try {
        realm = Realm.getInstance(realmConfiguration);
    } catch (Exception e) {
        Log.e("Realm init failed", e.getMessage());
    }
}

protected void saveObjectIntoDatabase(final RealmObject object) {
    realm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm bgRealm) {
            bgRealm.copyToRealm(object);    
        }
    }, new Realm.Transaction.OnSuccess() {
        @Override
        public void onSuccess() {
            // onSuccess
        }
    }, new Realm.Transaction.OnError() {
        @Override
        public void onError(Throwable error) {
            // onError
        }
    });
}

After creating the database-class i created an Interface to distinguish between Objects with a Primary Key and without.

public interface AutoIncrementable {
    public void setPrimaryKey(int primaryKey);
    public int getNextPrimaryKey(Realm realm);
}

Now you will just need to edit this code of the previous execute method

public void execute(Realm bgRealm) {
                if(object instanceof AutoIncrementable){
                    AutoIncrementable autoIncrementable = (AutoIncrementable) object;
                    autoIncrementable.setPrimaryKey(autoIncrementable.getNextPrimaryKey(bgRealm));
                    bgRealm.copyToRealm((RealmObject)autoIncrementable);
                } else {
                    bgRealm.copyToRealm(object);
                }
}

With this solution the database logic will still be in one class and this class can passed down to every class which needs to write into the database.

public class Person extends RealmObject implements AutoIncrementable{

    @PrimaryKey
    public int id;
    public String name;

    @Override
    public void setPrimaryKey(int primaryKey) {
        this.id = primaryKey;
    }

    @Override
    public int getNextPrimaryKey(Realm realm) {
        return realm.where(Person.class).max("id").intValue() + 1;
    }
}

Please give me some feedback. I am new to Realm and i thought it would be a good idea to handle it like this because i dont need to handle the primary key anymore because i only need to know the primary key when inserting into the database.

@Zhuinden

This comment has been minimized.

Show comment
Hide comment
@Zhuinden

Zhuinden Oct 21, 2016

Contributor

@kejith I think max returns null on first attempt, otherwise this works perfectly fine inside a transaction.

You should only do saveObjectIntoDatabase for one element at a time though, if you want to save a list, you should save the list in one transaction.

Contributor

Zhuinden commented Oct 21, 2016

@kejith I think max returns null on first attempt, otherwise this works perfectly fine inside a transaction.

You should only do saveObjectIntoDatabase for one element at a time though, if you want to save a list, you should save the list in one transaction.

@Zhuinden

This comment has been minimized.

Show comment
Hide comment
@Zhuinden

Zhuinden Oct 21, 2016

Contributor

This is how I'd do it:

 realm.executeTransaction(new Realm.Transaction() { // must be in transaction for this to work
     @Override
     public void execute(Realm realm) {
         Number currentIdNum = realm.where(User.class).max(UserFields.ID);
         int nextId;
         if(currentIdNum == null) {
            nextId = 1;
         } else {
            nextId = currentIdNum.intValue() + 1;
         }
         User user = new User(); // unmanaged
         user.setId(nextId);
         //...
         realm.insertOrUpdate(user); // using insert API
     }
 }
Contributor

Zhuinden commented Oct 21, 2016

This is how I'd do it:

 realm.executeTransaction(new Realm.Transaction() { // must be in transaction for this to work
     @Override
     public void execute(Realm realm) {
         Number currentIdNum = realm.where(User.class).max(UserFields.ID);
         int nextId;
         if(currentIdNum == null) {
            nextId = 1;
         } else {
            nextId = currentIdNum.intValue() + 1;
         }
         User user = new User(); // unmanaged
         user.setId(nextId);
         //...
         realm.insertOrUpdate(user); // using insert API
     }
 }
@kejith

This comment has been minimized.

Show comment
Hide comment
@kejith

kejith Oct 21, 2016

@Zhuinden thanks for your advise. I fixed the problem with the null pointer.

Number currentIdNum = realm.where(User.class).max(UserFields.ID);
I wanted to decouple Model-Classes from the execute-Method so i can reuse the execute for every RealmObject.

kejith commented Oct 21, 2016

@Zhuinden thanks for your advise. I fixed the problem with the null pointer.

Number currentIdNum = realm.where(User.class).max(UserFields.ID);
I wanted to decouple Model-Classes from the execute-Method so i can reuse the execute for every RealmObject.

@Zhuinden

This comment has been minimized.

Show comment
Hide comment
@Zhuinden

Zhuinden Oct 21, 2016

Contributor

Ah. Yeah, I've done that before, http://stackoverflow.com/a/31560557/2413303
If you add a getIdField() method, you can hide it per type.

Contributor

Zhuinden commented Oct 21, 2016

Ah. Yeah, I've done that before, http://stackoverflow.com/a/31560557/2413303
If you add a getIdField() method, you can hide it per type.

@kejith

This comment has been minimized.

Show comment
Hide comment
@kejith

kejith Oct 21, 2016

Thanks for your quick answer. I've watched your code (the code u linked) and i think that

public interface RealmRepository<T extends RealmObject, ID extends Serializable> {
    T findOne(Realm realm, ID id);

    RealmResults<T> findAll(Realm realm);

    T saveOrUpdate(Realm realm, T t);

    RealmList<T> saveOrUpdate(Realm realm, RealmList<T> tList);

    RealmQuery<T> query(Realm realm);

    void delete(Realm realm, ID id);

    void delete(Realm realm, T t);

    void delete(Realm realm, RealmResults<T> realmResults);

    void deleteAll(Realm realm);

    long count(Realm realm);
}

Could just be a static class to take a RealmObject and a Realm as parameters for every Method so it isnt needed to implement the Interface on every object?

kejith commented Oct 21, 2016

Thanks for your quick answer. I've watched your code (the code u linked) and i think that

public interface RealmRepository<T extends RealmObject, ID extends Serializable> {
    T findOne(Realm realm, ID id);

    RealmResults<T> findAll(Realm realm);

    T saveOrUpdate(Realm realm, T t);

    RealmList<T> saveOrUpdate(Realm realm, RealmList<T> tList);

    RealmQuery<T> query(Realm realm);

    void delete(Realm realm, ID id);

    void delete(Realm realm, T t);

    void delete(Realm realm, RealmResults<T> realmResults);

    void deleteAll(Realm realm);

    long count(Realm realm);
}

Could just be a static class to take a RealmObject and a Realm as parameters for every Method so it isnt needed to implement the Interface on every object?

@Zhuinden

This comment has been minimized.

Show comment
Hide comment
@Zhuinden

Zhuinden Oct 21, 2016

Contributor

Well I had a ___RepositoryImpl class for each class.

So it was like

public class DogRepositoryImpl 
      extends LongRealmRepositoryImpl<Dog> 
      implements DogRepository {
    public DogRepositoryImpl() {
         super(Dog.class);
    } 

    // getId, setId
} 
Contributor

Zhuinden commented Oct 21, 2016

Well I had a ___RepositoryImpl class for each class.

So it was like

public class DogRepositoryImpl 
      extends LongRealmRepositoryImpl<Dog> 
      implements DogRepository {
    public DogRepositoryImpl() {
         super(Dog.class);
    } 

    // getId, setId
} 

@Zhuinden Zhuinden referenced this issue Nov 6, 2016

Closed

Primary key #3751

@kinsleykajiva

This comment has been minimized.

Show comment
Hide comment
@kinsleykajiva

kinsleykajiva Nov 7, 2016

@kejith i have noticed that you offered a solution to this problem above you gave us a snippet:

public interface AutoIncrementable {
    public void setPrimaryKey(int primaryKey);
    public int getNextPrimaryKey(Realm realm);
}
public void execute(Realm bgRealm) {
                if(object instanceof AutoIncrementable){
                    AutoIncrementable autoIncrementable = (AutoIncrementable) object;
                    autoIncrementable.setPrimaryKey(autoIncrementable.getNextPrimaryKey(bgRealm));
                    bgRealm.copyToRealm((RealmObject)autoIncrementable);
                } else {
                    bgRealm.copyToRealm(object);
                }
}
public class Person extends RealmObject implements AutoIncrementable{

    @PrimaryKey
    public int id;
    public String name;

    @Override
    public void setPrimaryKey(int primaryKey) {
        this.id = primaryKey;
    }

    @Override
    public int getNextPrimaryKey(Realm realm) {
        return realm.where(Person.class).max("id").intValue() + 1;
    }
}

but you highlighted that the problem of null pointer at initial use.
*My advise or view * i think if you use the new Realm version at 2.1,1 in android it allows the use of default value so i think if you would set id default value the null pointer can be resolved i havent tried it yet but i will make use of it though... tell me what you think about the apporoach

kinsleykajiva commented Nov 7, 2016

@kejith i have noticed that you offered a solution to this problem above you gave us a snippet:

public interface AutoIncrementable {
    public void setPrimaryKey(int primaryKey);
    public int getNextPrimaryKey(Realm realm);
}
public void execute(Realm bgRealm) {
                if(object instanceof AutoIncrementable){
                    AutoIncrementable autoIncrementable = (AutoIncrementable) object;
                    autoIncrementable.setPrimaryKey(autoIncrementable.getNextPrimaryKey(bgRealm));
                    bgRealm.copyToRealm((RealmObject)autoIncrementable);
                } else {
                    bgRealm.copyToRealm(object);
                }
}
public class Person extends RealmObject implements AutoIncrementable{

    @PrimaryKey
    public int id;
    public String name;

    @Override
    public void setPrimaryKey(int primaryKey) {
        this.id = primaryKey;
    }

    @Override
    public int getNextPrimaryKey(Realm realm) {
        return realm.where(Person.class).max("id").intValue() + 1;
    }
}

but you highlighted that the problem of null pointer at initial use.
*My advise or view * i think if you use the new Realm version at 2.1,1 in android it allows the use of default value so i think if you would set id default value the null pointer can be resolved i havent tried it yet but i will make use of it though... tell me what you think about the apporoach

@iamtodor

This comment has been minimized.

Show comment
Hide comment
@iamtodor

iamtodor Mar 29, 2017

@beeender does your last action - adding the issue to 3.2 milestone mean we can expect to get the feature pretty soon?

iamtodor commented Mar 29, 2017

@beeender does your last action - adding the issue to 3.2 milestone mean we can expect to get the feature pretty soon?

@beeender

This comment has been minimized.

Show comment
Hide comment
@beeender

beeender Mar 29, 2017

Contributor

@iamtodor we will document it in 3.2 ... probably something like #469 (comment) Realm won't support native auto incremental id in a short term.

Contributor

beeender commented Mar 29, 2017

@iamtodor we will document it in 3.2 ... probably something like #469 (comment) Realm won't support native auto incremental id in a short term.

@Zhuinden

This comment has been minimized.

Show comment
Hide comment
@Zhuinden

Zhuinden Mar 29, 2017

Contributor

AtomicLong sounds like a bad idea in a synchronized scenario, also you need to initialize the atomic long on start-up. I've done that and it is a hassle.

Contributor

Zhuinden commented Mar 29, 2017

AtomicLong sounds like a bad idea in a synchronized scenario, also you need to initialize the atomic long on start-up. I've done that and it is a hassle.

@cmelchior

This comment has been minimized.

Show comment
Hide comment
@cmelchior

cmelchior Mar 29, 2017

Contributor

None of the strategies in this issue will work in a sync scenario. Only something like UUID.getRandom().toString() would. So this issue is purely about documenting how to generate local keys under the premise that the Realm will never be synced.

As noted in #469 (comment) Asking for auto-incremented ID's is usually the wrong question.

Contributor

cmelchior commented Mar 29, 2017

None of the strategies in this issue will work in a sync scenario. Only something like UUID.getRandom().toString() would. So this issue is purely about documenting how to generate local keys under the premise that the Realm will never be synced.

As noted in #469 (comment) Asking for auto-incremented ID's is usually the wrong question.

@cmelchior cmelchior self-assigned this Apr 7, 2017

@monajafi

This comment has been minimized.

Show comment
Hide comment
@monajafi

monajafi Apr 10, 2017

Here is my strategy for auto increment in sync scenario. but did not implement completely yet:
1- Cache RealmObject's ids which is created using UUID.randomUUId in separate Realm Object wether device is online or offline
2- Query cached ids then save the Realmresults in temp list and finally clear cached ids after device get online.
3- Query RealmObjects using their cached ids
4- Assign second id by incrementing 1 to max second id ( In my case second id is barcode number which needs to be autoincremented in sync condition).
In this method I have to wait until cached id's or RealmObjects to get synced completely before quering and deleting them. this is crucial for offline conflict resolution. As a workaround to this
I do the query and deletion after delay to give enough time to realm to get synced. this also will be solved using sync progress feature(requires both download and upload completion callback simultaneously not separately)

monajafi commented Apr 10, 2017

Here is my strategy for auto increment in sync scenario. but did not implement completely yet:
1- Cache RealmObject's ids which is created using UUID.randomUUId in separate Realm Object wether device is online or offline
2- Query cached ids then save the Realmresults in temp list and finally clear cached ids after device get online.
3- Query RealmObjects using their cached ids
4- Assign second id by incrementing 1 to max second id ( In my case second id is barcode number which needs to be autoincremented in sync condition).
In this method I have to wait until cached id's or RealmObjects to get synced completely before quering and deleting them. this is crucial for offline conflict resolution. As a workaround to this
I do the query and deletion after delay to give enough time to realm to get synced. this also will be solved using sync progress feature(requires both download and upload completion callback simultaneously not separately)

@monajafi

This comment has been minimized.

Show comment
Hide comment
@monajafi

monajafi Apr 10, 2017

By the way, RealmInteger( #4266) type can be used for id auto increment too.

monajafi commented Apr 10, 2017

By the way, RealmInteger( #4266) type can be used for id auto increment too.

@cmelchior cmelchior closed this Apr 19, 2017

@cmelchior cmelchior removed the S:P2 Backlog label Apr 19, 2017

@cmelchior

This comment has been minimized.

Show comment
Hide comment
@cmelchior

cmelchior Apr 19, 2017

Contributor

The website docs have been updated with a section on how to work with auto-incrementing IDs. This should hopefully provide insight into why they in most cases are not needed, and how to get similar semantics if needed.

If you feel that anything is missing or is unclear in that section, feel free to create a new issue with the details and I'll update it as fast as possible.

https://realm.io/docs/java/latest/#auto-incrementing-ids

Contributor

cmelchior commented Apr 19, 2017

The website docs have been updated with a section on how to work with auto-incrementing IDs. This should hopefully provide insight into why they in most cases are not needed, and how to get similar semantics if needed.

If you feel that anything is missing or is unclear in that section, feel free to create a new issue with the details and I'll update it as fast as possible.

https://realm.io/docs/java/latest/#auto-incrementing-ids

@kinsleykajiva

This comment has been minimized.

Show comment
Hide comment
@kinsleykajiva

kinsleykajiva Apr 20, 2017

@cmelchior Thanks for the tip, i have gone through the documentation though its almost similar to how i was doing it, but still they (Realm) could have published this a long time ago.

kinsleykajiva commented Apr 20, 2017

@cmelchior Thanks for the tip, i have gone through the documentation though its almost similar to how i was doing it, but still they (Realm) could have published this a long time ago.

@mrasif

This comment has been minimized.

Show comment
Hide comment
@mrasif

mrasif Dec 14, 2017

In case of ActiveAndroid ORM you do not need to write id column in model, It will automatic generate auto incremented value and you can simply use it.
I am giving a sample model below-

@Table(name="Items")
public class Item extends Model{
    @Column(name="name")
    public String name;
}

Instead of

@Table(name="Items")
public class Item extends Model{
    @Column(name="Id")
    public long id;
    @Column(name="name")
    public String name;
}

If item is an object of Item then you can simply get id by using

item.getId();
So, the correct model is first one. For reference you can click here.

mrasif commented Dec 14, 2017

In case of ActiveAndroid ORM you do not need to write id column in model, It will automatic generate auto incremented value and you can simply use it.
I am giving a sample model below-

@Table(name="Items")
public class Item extends Model{
    @Column(name="name")
    public String name;
}

Instead of

@Table(name="Items")
public class Item extends Model{
    @Column(name="Id")
    public long id;
    @Column(name="name")
    public String name;
}

If item is an object of Item then you can simply get id by using

item.getId();
So, the correct model is first one. For reference you can click here.

@adonyas

This comment has been minimized.

Show comment
Hide comment
@adonyas

adonyas Feb 19, 2018

hello every one my class looks like this i used it to set random id for book id but i want it to be sequential and increasing plz help

public void Random(){
Random rd=new Random();
txtbook1.setText(""+rd.nextInt(1000+1));

}

harry

adonyas commented Feb 19, 2018

hello every one my class looks like this i used it to set random id for book id but i want it to be sequential and increasing plz help

public void Random(){
Random rd=new Random();
txtbook1.setText(""+rd.nextInt(1000+1));

}

harry

@kinsleykajiva

This comment has been minimized.

Show comment
Hide comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment