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

cha*_*l03 151 android kotlin android-room

我正在创建一个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()
}
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*Pag 296

您需要使用该autoGenerate属性

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

@PrimaryKey(autoGenerate = true)
Run Code Online (Sandbox Code Playgroud)

参考这里

  • 谢谢,我正在寻找autoIncrement,这就是为什么无法找到. (3认同)
  • @MatPeg 如果我想要一个自行生成的主键,并且一个来自 REST `@Entity( PrimaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))` 的主键怎么办? (2认同)

All*_*oso 89

您可以@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()
}
Run Code Online (Sandbox Code Playgroud)

  • `foodId`不需要为null(但也可以).也可以使用默认值,例如.`var foodId:Int = 0`并且autogenerate可以正常工作. (19认同)
  • 来自java doc的@MichałBaran,当类型是原始java```int````或```long```时,0被视为null-able,当类型为Integer或Long时,null为空.既然Kotlin Int在非Jullable中作为原始int工作,那么你是对的```var foodId:Int = 0```将起作用,但是```var foodId:Int?因为Int?= 0```不起作用?在JVM中转换为Integer.@JMK,如果你把它设为0,你必须出一个不可为空的```int```,原因如上所述. (4认同)
  • 你可以用另一种方式写: `val jack = User(name = "Jack", phone= 1)` 在这种情况下,你可以从构造函数中删除 0 (4认同)
  • @neer17 因为 foodId 将由 Room 在插入时自动生成,所以很可能在构造函数中没有用它。 (4认同)
  • 我看到这种方法的问题在于它是一个数据类。当 Food 是一个数据类时(就像在代码段中一样),food 被用于 equals() 比较,因此具有不同 foodId 的两种食物可以被认为是相等的。使用具有默认值的命名参数将解决该问题。 (3认同)
  • @AllanVeloso 你能解释一下为什么将 `foodId` 放在正文中而不是放在构造函数中吗? (2认同)

Ren*_*tik 36

经过这么多答案后令人难以置信,但最后我的做法几乎没有什么不同。我不喜欢主键可以为空,我想将它作为第一个参数,并且还想在不定义它的情况下插入,而且它也不应该是 var。

@Entity(tableName = "employments")
data class Employment(
    @PrimaryKey(autoGenerate = true) val id: Long,
    @ColumnInfo(name = "code") val code: String,
    @ColumnInfo(name = "title") val name: String
){
    constructor(code: String, name: String) : this(0, code, name)
}
Run Code Online (Sandbox Code Playgroud)

  • 对于这种情况,甚至不需要创建额外的构造函数。只需将 0 作为默认参数添加到 id 中,您将自动能够使用构造函数,而无需额外声明: @PrimaryKey(autoGenerate = true) val id: Long = 0L, (4认同)
  • 现在,如何在不传递 id 作为参数的情况下调用此类 Employee?请告诉。 (2认同)

kun*_*kar 27

@PrimaryKey(autoGenerate = true)

@Entity
public class User {

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


    @PrimaryKey(autoGenerate = true)
    private int id;

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

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

}
Run Code Online (Sandbox Code Playgroud)

同时存储数据

 db.userDao().InsertAll(new User(0,sName,sPhone));
Run Code Online (Sandbox Code Playgroud)

在创建对象时将id设为(我的用例对象)

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

如果字段的类型是Integer或Long(Object)(或者其TypeConverter将其转换为Integer或Long),则Insert方法在插入项时将null视为未设置.

  • 如果要自动生成,为什么甚至让用户将id放在构造函数中? (3认同)
  • @Igor Ganapolsky是的,但是条目将使用该自定义ID生成[自动递增将不起作用]并且如果再次传递相同的ID,它将抛出异常“唯一约束失败”,因此您需要始终传递新的ID或使其成为[0或null],然后让自动递增为您完成这项工作。 (2认同)

Chr*_*gue 13

这对我有用:

@Entity(tableName = "note_table")
data class Note(
    @ColumnInfo(name="title") var title: String,
    @ColumnInfo(name="description") var description: String = "",
    @ColumnInfo(name="priority") var priority: Int,
    @PrimaryKey(autoGenerate = true) var id: Int = 0//last so that we don't have to pass an ID value or named arguments
)
Run Code Online (Sandbox Code Playgroud)

请注意,在将实体插入 Room 之前,id 是最后一个以避免在创建实体时必须使用命名参数。将其添加到房间后,在更新实体时使用 id。


小智 6

例如,如果您有一个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
)
Run Code Online (Sandbox Code Playgroud)

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

  • 每次我们创建一个新的用户对象时,我们都需要传递一个 id 字段。这可以避免吗? (24认同)
  • 是的,把`@PrimaryKey(autoGenerated = true) val id: Long?= null` 在构造函数之外,在类的主体上 (13认同)
  • 实际上,您可以简单地将 0 作为 ID。如果您设置了@PrimaryKey 选项,房间将自动生成一个 ID。 (4认同)
  • @Magritte Care 详细说明更多请? (2认同)
  • @Ispam 在我上面的回答中,我发布了完整课程的外观。 (2认同)

小智 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,
        "","","","")
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然此代码片段可能是解决方案,但 [包括解释](//meta.stackexchange.com/questions/114762/explaining-entirely-‌ code-based-answers) 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而那些人可能不知道您提出代码建议的原因。 (5认同)
  • 有很多答案,例如“使用`@PrimaryKey(autoGenerate = true)`”-您的答案是否为此线程添加了任何新内容? (4认同)

Lin*_*rie 5

在下面的示例中,当您创建新用户时,请按构造函数中的方式传递参数。Room 将自动生成 id。所有用户对象 id 已在 id setter 中设置为 int 默认值,因此不要调用 setId

@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(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

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

}
Run Code Online (Sandbox Code Playgroud)