Realm for Androidの主キーを指定してオブジェクトを取得する適切な方法はあるのでしょうか。私はobjectForPrimaryKey
がSwiftに存在する方法を知っていますが、Realm for Androidにはそのような対応物はないようです。realm.where(EventInfo.class).equalTo("id", eventInfo.id).findFirst();
を実行すると、無駄がたくさんあります(少なくとも手首にやさしいものではありません)。いくつかの方法がないのですか?現在Realm 1.0.1を使用しています
これが私がこのようなレルムリポジトリを持っている理由です(私が書いた)
_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];
そして、すべての可能な順列は役に立ちません!だから私はあきらめました...
注:RealmはStringおよびIntegralデータのみを主キーとして受け入れるため、Find.byKey
のStringおよびLongバージョンのみを実装しました。また、Longでは、ByteおよびIntegerフィールドのクエリも許可されます(希望します!)。
いくつかの方法が欠けていますか?
いいえ。ビーナーが述べたように、それは現在実装されていません。進行状況/ディスカッションを追跡できます ここ 。
ヘルパー関数は次のようになります
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();
}
}
ここではクラス固有のメソッドです。これは、各クラスが異なる主キータイプを持つ可能性があるためです。呼び出し元のクラスで管理するレルムインスタンスをそれに渡す必要があります。
新しいレルムでは、次の方法でDBのスキーマを使用して、テーブルの主キーにアクセスできます。
private String load(Class realmClass) {
return mRealm.getSchema().get(realmClass.getSimpleName()).getPrimaryKey();
}
私はアノテーションの専門家ではありません。フィールドでgetAnnotation()
を使用して、実行時に@PrimaryKey
の値をリフレクションで読み取ろうとしましたが、値は常にnull
です。 @Retention(RetentionPolicy.CLASS)
の。