如何将主键作为Room Persistence lib的自动增量


192

我正在创建一个Entity(Room Persistence lib)类Food,我想在其中将其foodId作为自动增量。

@Entity
class Food(var foodName: String, var foodDesc: String, var protein: Double, var carbs: Double, var fat: Double)
{
    @PrimaryKey
    var foodId: Int = 0
    var calories: Double = 0.toDouble()
}

如何设置foodId自动递增字段?


4
而不是0.toDouble()可以使用0.0do声明它为双
精度

1
您如何创建Food类的新实例?您是手动指定ID还是将其留空?
Zookey

2
给未来读者的注释-Room必须将主键设置为0才能将其视为未设置。如果您使用任何其他默认值(例如-1),Room将不会自动生成ID。
马丁梅尔卡

Answers:


370

您需要使用该autoGenerate属性

您的主键注释应如下所示:

@PrimaryKey(autoGenerate = true)

PrimaryKey的参考。


3
谢谢,我正在搜索autoIncrement,这就是为什么找不到的原因。
chandil03

嘿@MatPag如果我要在一个表中使用两个主键(复合主键),并且其中一个主键应自动递增,该怎么办?我该如何实现?你能在这里回答吗?
Priyanka Alachiya

1
@MatPeg如果我要拥有一个主生成的PrimaryKey和来自REST的主密钥,该@Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))怎么办?
murt,

@murt您需要一个复合主键,但是您无法完成您想实现的目标。在这里
MatPag

链接文档的重要部分:Insert methods treat 0 as not-set while inserting the item.
Micha

123

您可以这样添加@PrimaryKey(autoGenerate = true)

@Entity
data class Food(
        var foodName: String, 
        var foodDesc: String, 
        var protein: Double, 
        var carbs: Double, 
        var fat: Double
){
    @PrimaryKey(autoGenerate = true)
    var foodId: Int = 0 // or foodId: Int? = null
    var calories: Double = 0.toDouble()
}

34
foodId不需要为null(但可以为null)。也可以使用默认值,例如。var foodId: Int = 0并且自动生成将正常工作。
米哈尔巴兰

8
来自Java文档的@MichałBaran,当类型为原始Java int或时long,将0视为可为空,而当类型为Integer或Long时,则为null。由于Kotlin Int当不可空值在JVM中作为原始int起作用时,那么您是对的并且var foodId: Int = 0会起作用,但是var foodId: Int? = 0由于Int不会起作用?在JVM中被转换为Integer。@JMK,如果将其设置为0,int则由于上述原因,您必须将其设为null 。
艾伦·

2
您可以不用其他方式编写:val jack = User(name = "Jack", phone= 1)在这种情况下,您可以从构造函数中删除0
user7856586

1
我看到的这种方法的问题在于它是数据类。当Food是数据类(如代码段中)时,将food用于equals()比较,因此可以将两个具有foodId不同的食物视为相等。将命名参数与默认值一起使用将解决此问题。
Sotti

1
@AllanVeloso您能解释一下为什么foodId放在正文中而不是在构造函数中吗?
Neeraj Sewani

42

@PrimaryKey(autoGenerate = true)

@Entity
public class User {

    @PrimaryKey(autoGenerate = true)
    private int id;

    @ColumnInfo(name = "full_name")
    private String name;

    @ColumnInfo(name = "phone")
    private String phone;

    public User(){
    }

    //type-1
    public User(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    //type-2
    public User(int id, String name, String phone) {
        this.id = id;
        this.name = name;
        this.phone = phone;
    }

}

在存储数据时

 //type-1
 db.userDao().InsertAll(new User(sName,sPhone)); 

 //type-2
 db.userDao().InsertAll(new User(0,sName,sPhone)); 

1型

如果您没有传递主键的值,则默认情况下它将为0或null。

2型

零或零的ID创建对象(我的情况下,用户对象)

如果字段类型是long或int(或其TypeConverter将其转换为long或int),则在插入项目时,Insert方法会将0视为未设置。

如果字段的类型为Integer或Long(对象)(或其TypeConverter将其转换为Integer或Long),则在插入项目时,Insert方法会将null设置为未设置。


1
即使将自定义ID设置为autoGenerate,我们也可以将其传递给Entity吗?
IgorGanapolsky '18年

2
@Igor Ganapolsky是的,但是条目将使用该自定义ID生成[自动递增将不起作用]并且如果再次传递相同的ID,它将抛出异常“唯一约束失败”,因此您需要始终传递新的ID或使其成为[0或空],然后让自动递增为您完成这项工作。
kunal khedkar '18

3
如果要自动生成,为什么还要让用户将id放在构造函数中?
hellcast

在Kotlin中,您可以使用数据类并编写: val jack = User(name = "Jack", phone= 1)在这种情况下,可以从构造函数中删除0
user7856586

@hellcast如果您在查询数据库时未在构造器中包含id(正如我刚刚学到的那样,很难理解),它将不会分配id字段(它将是您在构造函数中使用其初始化的任何内容),因为我假设它在填充对象的字段时调用相同的构造函数。
阿里·希拉尼

6
@Entity(tableName = "user")
data class User(

@PrimaryKey(autoGenerate = true)  var id: Int?,
       var name: String,
       var dob: String,
       var address: String,
       var gender: String
)
{
    constructor():this(null,
        "","","","")
}

4
尽管此代码段可能是解决方案,但包括说明确实有助于提高帖子的质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
约翰

4
有许多类似“ use @PrimaryKey(autoGenerate = true)”的答案-您的答案是否为此线程添加了新内容?
barbsan

是的,它增加了-它展示了null如何覆盖自动生成的字段
玛丽安·帕迪齐奥(MarianPaździoch)

5

例如,如果您users要存储一个具有字段的实体,(firstname, lastname , email)并且想要自动生成的ID,则可以执行此操作。

@Entity(tableName = "users")
data class Users(
   @PrimaryKey(autoGenerate = true)
   val id: Long,
   val firstname: String,
   val lastname: String,
   val email: String
)

然后,Room将自动生成并自动增加id字段。


21
每次创建新的Users对象时,我们都需要传递一个id字段。可以避免吗?
Aditya Ladwa

10
是的,放在@PrimaryKey(autoGenerated = true) val id: Long? = null构造函数之外,放在类的主体上
Allan Veloso

1
@Magritte Care拟定更多详情?
Ispam

2
@Ispam在上面的回答中,我张贴了完整的类的外观。
艾伦·韦洛索

2
实际上,您只需将0作为ID。如果您设置了@PrimaryKey选项,Room会自动生成一个ID。
罗曼索

1

用上面的代码注释您的Entity类。

在Java中

@PrimaryKey(autoGenerate = true)
private int id;

在科特林

@PrimaryKey(autoGenerate = true)
var id: Int;

然后,Room会自动生成并自动增加id字段。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.