[英]Proper way to get Realm object by its primary key in Android Java
我想知道是否有一種正確的方法來檢索一個對象,因為它在Realm for Android中具有主鍵。 我知道方法objectForPrimaryKey
確實存在於Swift中,但在Realm for Android中似乎沒有這樣的對應物。 我真的認為做realm.where(EventInfo.class).equalTo("id", eventInfo.id).findFirst();
看起來很浪費(至少它不是手腕友好的)。 我錯過了一些方法嗎? 我目前正在使用Realm 1.0.1
這就是為什么我有像這樣的Realm存儲庫(我寫的)
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;
}
}
我繼承了一個名為findOne(realm, id);
喜歡
CalendarEvent event = calendarEventRepository.findOne(realm, id);
但是,默認情況下,它是realm.where(CalendarEvent.class).equalTo("id", id).findFirst();
我最終為此創建了一個幫助類。 我將使用它,直到Realm團隊實現這些方法。 我已經將類命名為Find
(您可以按照自己喜歡的方式對其進行重命名,因為命名事物和緩存失效是計算機科學中最難的事情 )。 我認為最好使用它而不是調用where().equalTo()
將主鍵的名稱作為字符串值傳遞。 這樣您就可以使用正確的主鍵字段。 這是代碼:
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);
}
}
用法很簡單:
// 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();
如果沒有給定對象的主鍵或者找不到該對象,它將返回null。 如果沒有主鍵,我考慮拋出異常,但認為它有點矯枉過正。
我真的很傷心Java泛型沒有C#泛型那么強大,因為我真的很想把這個方法調用如下:
Find.byKey<EventInfo>(realm, eventInfoId);
相信我,我試過了! 我到處搜索如何獲取方法的泛型類型返回值。 當它被證明是不可能的,因為Java擦除了泛型方法,我嘗試創建一個泛型類並使用:
(Class<T>)(ParameterizedType)getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
所有可能的排列無濟於事! 所以我放棄了......
注意:我只實現了Find.byKey
String和Long版本,因為Realm只接受String和Integral數據作為主鍵,Long也允許查詢Byte和Integer字段(我希望!)
我錯過了一些方法嗎?
不。 正如beeender所說,它目前尚未實施。 可以在此處跟蹤進度/討論。
輔助函數可能如下所示
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();
}
}
這是一個特定於類的方法,因為每個類可以有不同的主鍵類型。 您必須將一個領域實例傳遞給您在調用類中管理的實例。
使用新的Realm,您可以使用數據庫的模式以這種方式訪問表的主鍵:
private String load(Class realmClass) {
return mRealm.getSchema().get(realmClass.getSimpleName()).getPrimaryKey();
}
我在注釋方面不是很專業,我試圖通過反射在運行時讀取@PrimaryKey
值,在字段上使用getAnnotation()
,但值總是為null
,可能是因為@Retention(RetentionPolicy.CLASS)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.