我尝试使用ID作为参考从Realm获取数据。但是,在查询ID时,我发现Realm为所有元素(ID为0)提供了相同的ID。当我在模型的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()
答案 0 :(得分:65)
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;
}
}
我希望能让你开始。
答案 1 :(得分:10)
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;
}
我使用singleton factory for generating primary keys作为更通用的解决方案,性能更佳(每次都max("id")
无需查询AtomicInteger
)。
如果您需要更多上下文,可以在Realm Git Hub中进行长时间的讨论:Document how to set an auto increment id?
答案 2 :(得分:3)
如前所述,尚未支持自动增量。
但是对于那些使用 kotlin 并希望使用领域具有自动增量行为的人来说,这是其中一种可能性:
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
}
}}
答案 3 :(得分:0)
如果你的身份证长,那么:
val nextId = bgRealm.where(Branch::class.java).max("localId") as Long + 1
答案 4 :(得分:0)
可悲的是,我无法对其他答案发表评论,但我想添加到Vinicius` answer。
首先,在查找主键时,您不应该打开新的realm实例,尤其是当您不关闭它们时,因为这会增加最大可能的文件描述符数。
其次,虽然这是一个偏好,但你不应该将原始类型(或对象等价物)作为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
,即使Realm未跟踪的对象仍为RealmModel
个实例,因此只要您使用您的领域,它就可用相关课程。 Java等价物将是:
static long getNextId(RealmModel object, Realm realm, String idField)
{
long count = realm.where(object.class).max(idField);
return count + 1;
}
延迟编辑注意事项:如果您正在处理可能来自外部来源(例如其他数据库或网络)的数据,那么最好不要使用此方法,因为这会导致数据之间发生冲突在您的内部数据库中。相反,您应该使用max([id field name])
。请参阅前面的代码段,我已修改它们以适应此编辑。
答案 5 :(得分:0)
这是一个通用的解决方案,我个人创建了一个名为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?因为我讨厌Id的值为0,所以只需更改它即可。 希望它能帮助别人。
答案 6 :(得分:0)
//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);
答案 7 :(得分:-1)
//编辑
我在这个问题上找到了这个新的解决方案
@PrimaryKey
private Integer _id = RealmAutoIncrement.getInstance().getNextIdFromDomain(AccountType.class);
//原始答案
我只想分享我解决此问题的尝试,因为我不想一直传递主键值。首先,我创建了一个Database-Class来处理RealmObject的存储。
public class RealmDatabase {
Realm realm;
public RealmDatabase() {
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()
.name("test").schemaVersion(1).build();
try {
realm = Realm.getInstance(realmConfiguration);
} catch (Exception e) {
Log.e("Realm init failed", e.getMessage());
}
}
protected void saveObjectIntoDatabase(final RealmObject object) {
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm bgRealm) {
bgRealm.copyToRealm(object);
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
// onSuccess
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
// onError
}
});
}
在创建数据库类之后,我创建了一个接口来区分具有主键和没有主键的对象。
public interface AutoIncrementable {
public void setPrimaryKey(int primaryKey);
public int getNextPrimaryKey(Realm realm);
}
现在您只需要编辑上一个执行方法的代码
if(object instanceof AutoIncrementable){
AutoIncrementable autoIncrementable = (AutoIncrementable) object;
autoIncrementable.setPrimaryKey(autoIncrementable.getNextPrimaryKey(bgRealm));
bgRealm.copyToRealm((RealmObject)autoIncrementable);
} else {
bgRealm.copyToRealm(object);
}
使用此解决方案,数据库逻辑仍将在一个类中,并且此类可以传递给需要写入数据库的每个类。
public class Person extends RealmObject implements AutoIncrementable{
@PrimaryKey
public int id;
public String name;
@Override
public void setPrimaryKey(int primaryKey) {
this.id = primaryKey;
}
@Override
public int getNextPrimaryKey(Realm realm) {
return realm.where(Person.class).max("id").intValue() + 1;
}
}
如需进一步的建议,请随时在下面发表评论。