The correct way to get a Realm object by its primary key in Android Java

I wonder if there is a way to return an object, given its primary key in Realm for Android. I know that the objectForPrimaryKey method exists in Swift, but there seems to be no such analog in Realm for Android. I really think what to do realm.where(EventInfo.class).equalTo("id", eventInfo.id).findFirst(); It looks like a lot of waste (at least it is not suitable for the wrist). Did I skip some method? I am currently using Realm 1.0.1

+7
java android realm
source share
4 answers

That's why I have a Realm repository like this (which I wrote)

 public class CalendarEventRepositoryImpl extends LongRealmRepositoryImpl<CalendarEvent> implements CalendarEventRepository { public CalendarEventRepositoryImpl() { super(CalendarEvent.class); } @Override public Long getId(CalendarEvent calendarEvent) { return calendarEvent.getId(); } public void setId(CalendarEvent calendarEvent, Long id) { calendarEvent.setId(id); } public String getIdFieldName() { return CalendarEventFields.ID; } } 

and I inherit a method called findOne(realm, id); as

 CalendarEvent event = calendarEventRepository.findOne(realm, id); 

But yes, by default, it is realm.where(CalendarEvent.class).equalTo("id", id).findFirst();

+7
source share

Did I skip some method?

Nope. As mentioned by beeender, it is not currently implemented. Progress / discussion can be tracked here .

A helper function might look like this:

 public class Cat extends RealmObject { @PrimaryKey private int id; private String name; public Cat getByPrimaryKey(Realm realm, int id) { return realm.where(getClass()).equalTo("id", id).findFirst(); } } 

This is a class method because each class can have a different type of primary key. You must pass a realm instance to it, which you are managing in the calling class.

+3
source share

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!)

+3
source share

Using the new Realm, you can access the primary key of your table using your database schema as follows:

 private String load(Class realmClass) { return mRealm.getSchema().get(realmClass.getSimpleName()).getPrimaryKey(); } 

I'm not very good at annotation, I tried to read the @PrimaryKey value at runtime by reflecting using getAnnotation() in the fields, but the values ​​are always null , possibly due to @Retention(RetentionPolicy.CLASS) .

+1
source share

All Articles