NizarETH
NizarETH

Reputation: 1009

Custom method for ID in Realm to support auto increment behaviour

I worked with realm version 0.80 for a while, and as I knew Realm doesn't support auto increment behavior.
Therefore, I did this workaround :

public class Item extends RealmObject implements Serializable {

@PrimaryKey
private int id;
private int order;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public int getOrder() {
    return order;
}

public void setOrder(int order) {
    id = Increment.Primary_Cart(order); //this line for increment id
    this.order = order;
}

and this is my static method to increment id :

public static int Primary_Cart(int id){
    if(id>0) {
        id_Cart++;
    }
    return id_Cart;
}

Everyting works fine till I decided to upgrade Realm from version 0.80.0 to 0.90.1.
Then I had this error:

Caused by: io.realm.exceptions.RealmPrimaryKeyConstraintException: Value already exists: 0

To be more clear, I parse JSON using Realm, and some models don't have an ID, this is the reason why I used the above workaround, and I don't want to use another solution like GSON or something.
I need to do parsing and storage using only Realm because I had a huge project, and I thought to optimize it.

Upvotes: 0

Views: 1137

Answers (1)

Maiko Trindade
Maiko Trindade

Reputation: 3029

Nowadays Realm does not support autoIncrement feature, but this gist by carloseduardosx may be useful to you: https://gist.github.com/carloseduardosx/a7bd88d7337660cd10a2c5dcc580ebd0

It is a class whick implement autoIncrement specifically for Realm databases. It's not complex, the mosr relevant parts are these two methods:

/**
 * Search in modelMap for the last saved id from model passed and return the next one
 *
 * @param clazz Model to search the last id
 * @return The next id which can be saved in database for that model, 
 * {@code null} will be returned when this method is called by reflection
 */
public Integer getNextIdFromModel(Class<? extends RealmObject> clazz) {

    if (isValidMethodCall()) {
        AtomicInteger modelId = modelMap.get(clazz);
        if (modelId == null) {
            return 0;
        }
        return modelId.incrementAndGet();
    }
    return null;
}

/**
 * Utility method to validate if the method is called from reflection,
 * in this case is considered a not valid call otherwise is a valid call
 *
 * @return The boolean which define if the method call is valid or not
 */
private boolean isValidMethodCall() {
    StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
    for (StackTraceElement stackTraceElement : stackTraceElements) {

        if (stackTraceElement.getMethodName().equals("newInstance")) {
            return false;
        }
    }
    return true;
}

Upvotes: 1

Related Questions