通过Android Java中的主键获取Realm对象的正确方法

时间:2016-06-29 20:57:29

标签: java android realm

我想知道是否有一种正确的方法来检索一个对象,因为它是Realm for Android中的主键。我知道方法objectForPrimaryKey确实存在于Swift中,但在Realm for Android中似乎没有这样的对应物。我真的认为做realm.where(EventInfo.class).equalTo("id", eventInfo.id).findFirst();看起来很浪费(至少它不是手腕友好的)。我错过了一些方法吗?我目前正在使用Realm 1.0.1

4 个答案:

答案 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