如何在Realm Android中设置自动增量主键

33

我想为我的表设置自增主键。

这是我的类。我已经设置了主键,但我希望它成为自增主键。

public class users extends RealmObject {

@PrimaryKey
private int id;
private long icn;
private String name;
private String email;
private String password;
private int phone;

public String getName() {
    return name;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public long getIcn() {
    return icn;
}

public void setIcn(long icn) {
    this.icn = icn;
}

public void setName(String name) {
    this.name = name;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public int getPhone() {
    return phone;
}

public void setPhone(int phone) {
    this.phone = phone;
}

}

谢谢您提前。


1
可能是Realm自动增量字段示例的重复问题。 - R. Zagórski
我正在寻找 Realm 中的内置属性,它可以像其他数据库一样自动递增。 - Maaz Patel
你找不到它,因为它不存在。主要是因为只需要六行代码就可以轻松实现,所以它从未成为一个高优先级的任务。 - EpicPandaForce
Realm是一种对象数据库,它存储对象图。表在索引时使用主键,但是在Realm中没有这样的东西,Realm使用@PrimaryKey来方便地进行索引。 - Alex Shutov
@AlexShutov 嗯,主键对于识别对象以便稍后更新非常重要,并且对于新发布的 Realm Object Server 的同步逻辑而言也相当重要。但是你设置什么作为主键基本上取决于你自己。 - EpicPandaForce
9个回答

49

在交易中,您可以始终可靠地访问当前的最大ID,基于该ID,您可以递增它并将其用作下一个ID的基础。

 realm.executeTransaction(new Realm.Transaction() { // must be in transaction for this to work
     @Override
     public void execute(Realm realm) {
         // increment index
         Number currentIdNum = realm.where(users.class).max(usersFields.ID);
         int nextId;
         if(currentIdNum == null) {
            nextId = 1;
         } else {
            nextId = currentIdNum.intValue() + 1;
         }
         users user = new users(); // unmanaged
         user.setId(nextId);
         //...
         realm.insertOrUpdate(user); // using insert API
     }
 }

1
顺便提一下,对于同步领域来说,这有点棘手,通常最好使用随机UUID。或者在支持时使用RealmCounter。 - EpicPandaForce
@EpicPandaForce 当您直接将JSON编写到Realm中并且希望自动生成主键值时,您该如何处理?如果您可以添加第二个注释,例如RealmAutoGenerate,那将非常好。 - Hector
如果您使用createAllFromJson等方法,则可能无法自动执行该操作。 - EpicPandaForce

12

这是一个旧的问题并且已经有了答案,但我想发布另一种解决方案。 你可以像这样做:

Realm realm = Realm.getDefaultInstance();
// Realm transaction
realm.executeTransactionAsync(new Realm.Transaction() { 
    @Override
     public void execute(Realm bgRealm) {
         // Get the current max id in the users table
         Number maxId = bgRealm.where(users.class).max("id");
         // If there are no rows, currentId is null, so the next id must be 1
         // If currentId is not null, increment it by 1
         int nextId = (maxId == null) ? 1 : maxId.intValue() + 1;
         // User object created with the new Primary key
         users user = bgRealm.createObject(users.class, nextId);
         // Now you can update your object with your data. The object will be
         // automatically saved in the database when the execute method ends
         // ...
         // ... 
    }
}

4

好的,@PrimaryKey只是表示该字段是一个键。但是在创建对象并将其复制到Realm时需要自己设置它。考虑使用UUID.random()或手动递增它。(参见评论中的答案):Realm自动递增字段示例


1
抱歉,复制了错误选项卡的地址:https://dev59.com/dl0Z5IYBdhLWcg3wpRlW - Alex Shutov

2

在 Kotlin 中

我的接口

fun getRegistroIdentity(): Int

我的方法
class RegistroOver(private val realm: Realm) : RegistroImplementation {

override fun getRegistroIdentity(): Int {
    val registro = realm.where(Registro::class.java).max("id")
    val result: Int
    result = if (registro == null) {
        1
    } else {
        registro.toInt() + 1
    }
    return result
}}

:)


1

这里有一个示例,可以使用序列来实现主键 id 的自动增加:

https://raw.githubusercontent.com/505aaron/realm-migration-example/master/realm/sequencer.js

const sequencer = (realmInstance, schema, props) => new Promise((resolve, reject) => {
  let saved;

  try {
    realmInstance.write(() => {
      const obj = { ...props };

      if (typeof obj.id === 'undefined') {
        let seq = realmInstance.objects('Sequence').filtered(`name = "${schema}"`)[0];
        if (typeof seq === 'undefined') {
          seq = realmInstance.create('Sequence', { name: schema, value: 0 });
        }
        obj.id = seq.next();
      }
      saved = realmInstance.create(schema, obj, true);

      resolve({ ...saved });
    });
  } catch (e) {
    reject(e);
  }
});

export default sequencer;

1
一个更短的答案可以是这样的:

    Person person = new Person();
    person.setName("UserName");

    realm.beginTransaction();

    Number newId = realm.where(Person.class).max("id");
    person.setId(newId.intValue()+1);

    realm.copyToRealm(person);
    realm.commitTransaction();

0

针对React Native

...
// this is the part where you are saving the newItem
realm.write(() => {
    // handle the id
    let id: any = realm.objects(this.Schema).max("id");
    newItem.id = id === undefined ? 1 : id++;
    realm.create(this.Schema, newItem);
    resolve(newItem);
});

1
这应该是++id而不是id++,对吗? - Philipp Sumi

-1

我使用这个。

public static int nextID(Class table) {
        return instance.realm.where(table).findAll().max("id").intValue() + 1;
    }

所以我想要增加Person类的Id属性值,

netID(Person.class);

-3
在我的个人情况下,我将ID设置为Unix时间值。我知道它不是递增的,但是它是唯一的。
(int) System.currentTimeMillis() / 1000;

1
如果在一秒钟内插入了2条记录,则会抛出错误。 - Maaz Patel
@MaazPatel 嗯,没错。我会尝试模拟你的评论,因为我的应用程序不会同时插入两个项目。 - Moises Portillo
你不应该将它转换为整数...那样不是更好的选择。 - 476rick
3
如果用户将时间往回调整一个小时左右会怎样? - Ridcully

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接