Eenvincible Eenvincible - 4 months ago 15
Android Question

Realm Query Returns Incomplete Results Set In Android

I have been having a very unusual behavior when using

Realm
to
insert
and
read/query
data. Here is what is happening to be precise:

Initial Status

When I start to insert data to the database, everything works fine. I have the following code to handle
autoIncrementingId
since I have not found a version of
Realm
that offers this out of the box!

CashOrder cashOrder = new CashOrder();

realm.beginTransaction();

int lastCashOrderId;
RealmResults<CashOrder> cashOrders = realm.where(CashOrder.class).findAll();

cashOrders.sort("id", Sort.ASCENDING);

if (cashOrders.isEmpty()){
cashOrder.setId("0");
}else{
lastCashOrderId = Integer.parseInt(cashOrders.last().getId());
cashOrder.setId(String.valueOf(lastCashOrderId + 1));
}

//the rest of the code here

//then copyToRealm here;

realm.copyToRealm(cashOrder);
realm.commitTransaction();


The problem

Insertion of data into the
database
works just fine but the moment the id value reaches
10
- implying 11 items in the table since my id starts at
(0)
, I get a
Realm Primary Key Exception
which basically complains that I am trying to add an already existing object.

I am explicitly calling
realm.copyToRealm(obj)
instead of
realm.copyToRealmOrUpdate(obj)
because that is what I want to do. Updates only are allowed when doing an Edit.

I am stuck here and I can't seem to figure out what is causing this issue!

More information

I am using:

compile 'io.realm:realm-android:0.87.4'


I will truly appreciate your help on this! Thanks in advance!

Answer

It's because your ID is a STRING and therefore it's ordered as 1, 10, 2, 3, ... 9.

This means when you evaluate the "next ID" when you had already inserted "10",

lastCashOrderId = Integer.parseInt(cashOrders.last().getId()); 

lastCashOrderId will be 9, and you'll be inserting 10 again.

Solution: use long id for longs, or re-think your auto-increment IDs (f.ex. use UUID.randomString() or something)

P.S. you should use findAllSorted() instead of findAll().sort() for consistent behavior when you update to the newer Realm versions.

EDIT: please use long newId = realm.where(CashOrder.class).max("age").longValue() + 1; to evaluate the new ID, and do this while you're in a transaction.