I have finished creating for this helper class. I will use it until the Realm team executes these methods. I called the Find class (you can rename it the way you like, since naming things and invalidating the cache are the most difficult things in computer science ). I think it's better to use this than to call where().equalTo() , passing the name of the primary key as a string value. Thus, you will definitely use the correct primary key field. Here is the code:
import java.util.Hashtable; import io.realm.Realm; import io.realm.RealmModel; import io.realm.RealmObjectSchema; public final class Find { // shared cache for primary keys private static Hashtable<Class<? extends RealmModel>, String> primaryKeyMap = new Hashtable<>(); private static String getPrimaryKeyName(Realm realm, Class<? extends RealmModel> clazz) { String primaryKey = primaryKeyMap.get(clazz); if (primaryKey != null) return primaryKey; RealmObjectSchema schema = realm.getSchema().get(clazz.getSimpleName()); if (!schema.hasPrimaryKey()) return null; primaryKey = schema.getPrimaryKey(); primaryKeyMap.put(clazz, primaryKey); return primaryKey; } private static <E extends RealmModel, TKey> E findByKey(Realm realm, Class<E> clazz, TKey key) { String primaryKey = getPrimaryKeyName(realm, clazz); if (primaryKey == null) return null; if (key instanceof String) return realm.where(clazz).equalTo(primaryKey, (String)key).findFirst(); else return realm.where(clazz).equalTo(primaryKey, (Long)key).findFirst(); } public static <E extends RealmModel> E byKey(Realm realm, Class<E> clazz, String key) { return findByKey(realm, clazz, key); } public static <E extends RealmModel> E byKey(Realm realm, Class<E> clazz, Long key) { return findByKey(realm, clazz, key); } }
The use is simple:
// now you can write this EventInfo eventInfo = Find.byKey(realm, EventInfo.class, eventInfoId); // instead of this EventInfo eventInfo = realm.where(EventInfo.class).equalTo("id", eventInfo.id).findFirst();
It will return null if the primary key for this object is missing or the object is not found. I thought about throwing an exception if there was no primary key, but decided that was redundant.
I was very sad that Java generics are not as strong as C # generators, because I really really would like to call the method as follows:
Find.byKey<EventInfo>(realm, eventInfoId);
And believe me, I tried! I searched everywhere how to get the return value of a generic type of a method type. When this turned out to be impossible, since Java erases common methods, I tried to create a common class and use:
(Class<T>)(ParameterizedType)getClass() .getGenericSuperclass()).getActualTypeArguments()[0];
And all possible permutations are useless! So I gave up ...
Note. I only implemented String and Long versions of Find.byKey , because Realm only accepts string and integral data as primary keys, and Long also allows you to query Byte and Integer fields (hopefully!)