Manera correcta de obtener el objeto Realm por su clave principal en Android Java
Me pregunto si hay una manera correcta de recuperar un objeto dado su clave primaria en Realm para Android. Sé que el método objectForPrimaryKey
existe en Swift, pero parece que no hay tal contrapartida en Realm para Android. Realmente creo que haciendo realm.where(EventInfo.class).equalTo("id", eventInfo.id).findFirst();
parece un montón de residuos (al menos no es muñeca-friendly). ¿Me falta algún método? Actualmente estoy utilizando Realm 1.0.1
- Android Realm número de versión de migración basado en qué?
- Diferencia entre RealmResults y RealmList
- Realm.io y consultas asincrónicas
- Restricción única del reino en varios campos
- Manera correcta de abstraer el reino en las aplicaciones de Android
- Android - Prueba de un recurso de cadena con Robolectric
- Acceso al dominio desde un subproceso incorrecto Android
- Realm.io de Android cómo sincronizar con el lado del servidor MySQL DB
- RealmResult consulta de nuevo
- Usar reino en una biblioteca-aar
- Realm + Retrofit + Rxjava
- Kotlin uso perezoso
- Error de acceso de realm de subproceso incorrecto al usar código compartido entre IntentService y AsyncTask (Android)
Esta es la razón por la que tengo un repositorio Realm como éste (el cual escribí)
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; } }
y findOne(realm, id);
un método llamado findOne(realm, id);
me gusta
CalendarEvent event = calendarEventRepository.findOne(realm, id);
Pero sí, por defecto, es realm.where(CalendarEvent.class).equalTo("id", id).findFirst();
¿Me falta algún método?
Nope. Como mencionó beeender, no está implementado actualmente. El progreso / discusión puede ser rastreado aquí .
Una función auxiliar podría verse así
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(); } }
Es un método específico de clase porque cada clase puede tener un tipo de clave primaria diferente. Tienes que pasar una instancia de dominio a la que administras en la clase de llamada.
He terminado creando una clase de ayuda para esto. Lo usaré hasta que el equipo Realm implemente estos métodos. He llamado a la clase Find
(puede cambiar el nombre de la manera que desee, ya que nombrar las cosas y la invalidación de caché son las cosas más difíciles en la informática ). Creo que es mejor usar esto que llamar a where().equalTo()
pasando el nombre de la clave primaria como un valor de cadena. De esta manera, seguro que utilizará el campo de clave principal correcto. Aquí está el código:
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); } }
El uso es sencillo:
// 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();
Volverá null si no hay una clave primaria para el objeto dado o si el objeto no se encuentra. Consideré lanzar una excepción si no había clave primaria, pero decidí que era exagerado.
Yo estaba realmente triste genéricos Java no son tan poderosos como genéricos C #, porque realmente, realmente me encantaría llamar al método de la siguiente manera:
Find.byKey<EventInfo>(realm, eventInfoId);
Y créanme lo intenté! He buscado por todas partes cómo obtener el valor genérico de un método de retorno de método. Cuando resultó imposible, ya que Java borra los métodos genéricos, intenté crear una clase genérica y usar:
(Class<T>)(ParameterizedType)getClass() .getGenericSuperclass()).getActualTypeArguments()[0];
Y todas las permutaciones posibles en vano! Así que me di por vencido …
Nota: Sólo implementé las versiones Cadena y Larga de Find.byKey
porque Realm acepta sólo los datos String y Integral como claves primarias, y Long permitirá la consulta de campos Byte y Integer también (¡espero!).
Con el nuevo Realm puedes acceder a la clave primaria de tu tabla usando el esquema de tu DB de esta manera:
private String load(Class realmClass) { return mRealm.getSchema().get(realmClass.getSimpleName()).getPrimaryKey(); }
No soy muy experto en anotación, he intentado leer el valor de @PrimaryKey
en tiempo de ejecución por reflexión, usando getAnnotation()
en los campos, pero los valores siempre son null
, tal vez debido a @Retention(RetentionPolicy.CLASS)
.