J'essaie d'obtenir des données de Realm en utilisant un identifiant comme référence. Cependant, lors de la recherche d'un ID, j'ai constaté que Realm me donnait le même ID pour tous les éléments (ID de 0). Pourquoi l'incrémentation automatique de l'ID ne se produit-elle pas lorsque j'utilise l'annotation @PrimaryKey
sur l'ID du modèle?
Voici la classe raccourcie pour le modèle:
public class Child_pages extends RealmObject {
@PrimaryKey
private int id_cp;
private int id;
private String day;
private int category_id;
Et la requête que j'exécute est: realm.where(Child_pages.class).equalTo("id_cp",page_id).findFirst()
Le royaume ne prend actuellement pas en charge l'incrémentation automatique des clés primaires. Cependant, vous pouvez facilement l'implémenter vous-même en utilisant quelque chose comme:
public int getNextKey() {
try {
Number number = realm.where(object).max("id");
if (number != null) {
return number.intValue() + 1;
} else {
return 0;
}
} catch (ArrayIndexOutOfBoundsException e) {
return 0;
}
}
J'espère que cela peut vous aider à démarrer.
La liaison Java ne prend pas encore en charge les clés primaires, mais elle figure dans la feuille de route et avec une priorité élevée - voir: https://groups.google.com/forum/#!topic/realm-Java/6hFqdyoH67w Pour contourner le problème, vous pouvez utiliser ce morceau de code pour générer des clés:
int key;
try {
key = realm.where(Child_pages.class).max("id").intValue() + 1;
} catch(ArrayIndexOutOfBoundsException ex) {
key = 0;
}
J'utilise singleton factory pour générer des clés primaires en tant que solution plus générique et offrant de meilleures performances (inutile de rechercher max("id")
à chaque fois grâce à AtomicInteger
).
Il y a une longue discussion dans Realm Git Hub si vous avez besoin de plus de contexte: Documentez comment définir un identifiant d'incrémentation automatique?
Comme déjà mentionné, l'incrémentation automatique n'est pas encore prise en charge.
Mais pour ceux qui utilisent kotlin et qui veulent avoir un comportement auto-incrémenté avec le royaume, voici une des possibilités:
open class Route(
@PrimaryKey open var id: Long? = null,
open var total: Double? = null,
open var durationText: String? = null,
open var durationMinutes: Double? = null,
open var distanceText: String? = null,
open var distanceMeters: Int? = null): RealmObject() {
companion object {
@Ignore var cachedNextId:Long? = null
get() {
val nextId = if (field!=null) field?.plus(1)
else Realm.getDefaultInstance()?.where(Route::class.Java)?.max("id")?.toLong()?.plus(1) ?: 1
Route.cachedNextId = nextId
return nextId
}
}}
si votre identifiant est long, alors:
val nextId = bgRealm.where(Branch::class.Java).max("localId") as Long + 1
Voici une solution générique. Personnellement, je crée une classe nommée RealmUtils et j'ajoute ce type de méthodes:
public static int getPrimaryKey(Class c)
{
Realm realm = Realm.getDefaultInstance();
String primaryKeyFied = realm.getSchema().get(c.getSimpleName()).getPrimaryKey();
if (realm.where(c).max(primaryKeyFied)== null)
return 1;
int value = realm.where(c).max(primaryKeyFied).intValue();
return value+1;
}
Pourquoi je retourne 0 quand la table est vide? Parce que je déteste les identifiants avec 0 comme valeur, alors changez-les simplement .. J'espère que cela aidera quelqu'un.
//generates primary key
public static int getNextKey(RealmQuery realmQuery, String fieldName) {
try {
Number number = realmQuery.max(fieldName);
if (number != null) {
return number.intValue() + 1;
} else {
return 1;
}
} catch (ArrayIndexOutOfBoundsException e) {
return 1;
}
}
Exemple
int id = RealmDbHelper.getNextKey(realm.where(RealmDocument.class), RealmDocument.FIELD_DOCUMENT_ID)
realmObject.setId(id);
realm.insert(realmObject);
Malheureusement, je ne peux pas commenter d'autres réponses, mais j'aimerais ajouter à la réponse de Vinicius .
Tout d'abord, vous ne devriez pas ouvrir une nouvelle instance de domaine lorsque vous recherchez une clé primaire, en particulier lorsque vous ne la fermez pas, car cela ajoute au nombre maximal de descripteurs de fichier possible.
Deuxièmement, bien que ce soit une préférence, vous ne devriez pas avoir de types primitifs (ou d’équivalents d’objets) nullables (dans Kotlin), car cela ajoute une obligation redondante de vérifier la nullité.
Troisièmement, puisque vous utilisez kotlin, vous pouvez simplement définir une méthode d'extension à la classe Realm
, telle que:
fun Realm.getNextId(model: RealmModel, idField : String) : Long
{
val count = realm.where(model::class.Java).max(idField)
return count + 1L
}
Étant donné que toutes les instances RealmObject
sont RealmModel
et que même les objets qui ne sont pas suivis par Realm sont toujours des instances RealmModel
, ils seront donc disponibles partout où vous utiliserez vos classes liées au domaine. L'équivalent Java serait:
static long getNextId(RealmModel object, Realm realm, String idField)
{
long count = realm.where(object.class).max(idField);
return count + 1;
}
Note d'édition tardive: Il est préférable de ne pas utiliser cette approche si vous traitez avec des données qui pourraient provenir de sources extérieures, telles que d'autres bases de données ou du Web, car cela entraînerait des conflits entre les données de votre base de données interne. Au lieu de cela, vous devriez utiliser max([id field name])
. Voir les extraits précédents, je les ai déjà modifiés pour tenir compte de cette modification.