我想知道是否有一种正确的方法来检索一个对象,因为它是Realm for Android中的主键。我知道方法objectForPrimaryKey
确实存在于Swift中,但在Realm for Android中似乎没有这样的对应物。我真的认为做realm.where(EventInfo.class).equalTo("id", eventInfo.id).findFirst();
看起来很浪费(至少它不是手腕友好的)。我错过了一些方法吗?我目前正在使用Realm 1.0.1
答案 0 :(得分:7)
这就是为什么我有一个像我这样的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();
答案 1 :(得分:6)
我最终为此创建了一个帮助类。在Realm团队实施这些方法之前,我一直在使用它。我已将该类命名为Find
(您可以按照自己喜欢的方式对其进行重命名,因为命名和缓存失效为the hardest things in computer science)。我认为使用它比调用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字段(我希望!)
答案 2 :(得分:3)
我错过了一些方法吗?
不。正如提到的那样,它目前尚未实施。可以跟踪进度/讨论here。
辅助函数可能如下所示
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();
}
}
这是一个特定于类的方法,因为每个类可以有不同的主键类型。您必须将一个领域实例传递给您在调用类中管理的实例。
答案 3 :(得分:1)
使用新的Realm,您可以使用数据库的架构以这种方式访问表的主键:
private String load(Class realmClass) {
return mRealm.getSchema().get(realmClass.getSimpleName()).getPrimaryKey();
}
我在注释方面不是很专业,我尝试在运行时通过反射在@PrimaryKey
上使用getAnnotation()
来读取null
的值,但值始终是@Retention(RetentionPolicy.CLASS)
,也许因为title
。