IDを参照として使用して、Realmからデータを取得しようとしています。しかし、IDを照会すると、Realmがすべての要素に同じID(IDが0)を与えていることがわかりました。モデルのIDで_@PrimaryKey
_注釈を使用すると、IDが自動インクリメントしないのはなぜですか?
モデルの短縮クラスは次のとおりです。
_public class Child_pages extends RealmObject {
@PrimaryKey
private int id_cp;
private int id;
private String day;
private int category_id;
_
そして、私が実行しているクエリは次のとおりです。realm.where(Child_pages.class).equalTo("id_cp",page_id).findFirst()
Realmは現在、主キーの自動インクリメントをサポートしていません。ただし、次のようなものを使用して自分で簡単に実装できます。
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;
}
}
それがあなたを始めさせることを願っています。
Javaバインディングは主キーをまだサポートしていませんが、ロードマップ上にあり、優先度が高くなっています- https://groups.google.com/forum/#! topic/realm-Java/6hFqdyoH67w 。回避策として、次のコードを使用してキーを生成できます。
int key;
try {
key = realm.where(Child_pages.class).max("id").intValue() + 1;
} catch(ArrayIndexOutOfBoundsException ex) {
key = 0;
}
私は シングルキーファクトリを使用して、主キー を生成し、パフォーマンスが向上したより一般的なソリューションとして使用します(AtomicInteger
のおかげで毎回max("id")
を照会する必要はありません)。
より多くのコンテキストが必要な場合は、Realm Git Hubで長い議論があります: 自動インクリメントIDの設定方法を文書化しますか?
既に述べたように、自動インクリメントはまだサポートされていません。
しかし、kotlinを使用し、レルムで自動インクリメント動作を行いたい場合、これは可能性の1つです。
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
}
}}
あなたのIDが長い場合:
val nextId = bgRealm.where(Branch::class.Java).max("localId") as Long + 1
ここに一般的な解決策があります。個人的にRealmUtilsという名前のクラスを作成し、このタイプのメソッドを追加します。
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;
}
テーブルが空のときに0を返すのはなぜですか?私は値が0のIdが嫌いなので、変更するだけです。それが誰かを助けることを願っています。
//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;
}
}
例
int id = RealmDbHelper.getNextKey(realm.where(RealmDocument.class), RealmDocument.FIELD_DOCUMENT_ID)
realmObject.setId(id);
realm.insert(realmObject);
悲しいことに、他の回答についてコメントすることはできませんが、 Vinicius` answer に追加したいと思います。
まず、主キーを検索するとき、特にそれらを閉じないときは、新しいレルムインスタンスを開くべきではありません。これにより、可能な最大ファイル記述子数が増加します。
第二に、これは優先事項ですが、冗長な要件が追加されるため、nullables(Kotlin)としてプリミティブ型(または同等のオブジェクト)を使用しないでください。ヌル可能性を確認します。
第三に、kotlinを使用しているため、次のような拡張メソッドをRealm
クラスに定義するだけです。
_fun Realm.getNextId(model: RealmModel, idField : String) : Long
{
val count = realm.where(model::class.Java).max(idField)
return count + 1L
}
_
すべてのRealmObject
インスタンスはRealmModel
であり、レルムによって追跡されないオブジェクトでさえRealmModel
インスタンスであるため、レルム関連のクラスを使用する場所であればどこでも使用可能です。 。 Java同等のものは:
_static long getNextId(RealmModel object, Realm realm, String idField)
{
long count = realm.where(object.class).max(idField);
return count + 1;
}
_
後期編集ノート:他のデータベースやWebなどの外部ソースからのデータを処理する場合は、この方法を使用しない方がよいでしょう。これは、内部データベースのデータ間で衝突が発生するためです。代わりに、max([id field name])
を使用する必要があります。前のスニペットを参照してください。この編集に対応するために、すでに変更しています。