Cómo hacer una clave primaria como autoincremento para lib de persistencia de habitación

197

Estoy creando un alimento de clase Entity (Room Persistence lib), donde quiero hacer foodIdcomo autoincremento.

@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()
}

¿Cómo puedo configurar foodIdun campo de autoincremento?

chandil03
fuente
44
En lugar de 0.toDouble()usar, puede 0.0declararlo como un doble
RobCo
2
¿Cómo se crea una nueva instancia de la clase Food? ¿Especificas ID manualmente o lo dejas en blanco?
Zookey
3
Una nota para futuros lectores: la clave principal debe ser 0 para que Room la trate como no configurada. Si usa cualquier otro valor predeterminado (por ejemplo, -1), Room no generará automáticamente la identificación.
Martin Melka

Respuestas:

376

Necesitas usar la autoGeneratepropiedad

Su anotación de clave principal debería ser así:

@PrimaryKey(autoGenerate = true)

Referencia para PrimaryKey .

MatPag
fuente
3
Gracias, estaba buscando autoIncrement, por eso no pude encontrarlo.
chandil03
Hola @MatPag, ¿qué pasa si quiero dos claves principales en una tabla (claves primarias compuestas) y una de las claves principales debe incrementarse automáticamente? ¿Cómo puedo lograr eso? ¿Puedes responder esto aquí ?
Priyanka Alachiya
1
@MatPeg ¿Qué sucede si quiero tener una PrimaryKey que se genere automáticamente y que provenga de REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
murt
@murt Necesita una clave primaria compuesta, pero no puede hacer lo que quiere lograr. Lea aquí
MatPag
Parte importante de la documentación vinculada:Insert methods treat 0 as not-set while inserting the item.
Micha
127

Puedes agregar @PrimaryKey(autoGenerate = true)así:

@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()
}
Allan Veloso
fuente
35
foodIdno necesita ser nulo (pero puede serlo). También se podrían usar valores predeterminados, por ejemplo. var foodId: Int = 0y el autogenerado funcionaría correctamente.
Michał Baran
8
@ MichałBaran, del documento java, cuando el tipo es un Java primitivo into long, 0 se trata como nulo, cuando el tipo es Entero o Largo, nulo es nulo. Dado que Kotlin Int cuando los valores no nulables funcionan en JVM como int primitivo, ¿tiene razón y var foodId: Int = 0funcionará, pero var foodId: Int? = 0no funcionará desde Int? se convierte en JVM como Integer. @JMK, si lo pone a 0, DEBE hacer un no anulable intpor la razón mencionada anteriormente.
Allan Veloso el
3
Puede escribir sin de otra manera: val jack = User(name = "Jack", phone= 1)en este caso, puede eliminar 0 del constructor
user7856586
2
@AllanVeloso ¿Puede explicar por qué foodIdse colocó en el cuerpo y no en el constructor?
Neeraj Sewani
2
@ neer17 ya que el foodId será generado automáticamente por Room en la inserción, lo más probable es que no sea útil tenerlo en el constructor.
Allan Veloso
42

añadir @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;
    }

}

mientras almacena datos

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

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

tipo 1

Si no está pasando el valor de la clave primaria, por defecto será 0 o nulo.

tipo 2

Poner nulo o cero para la identificación al crear el objeto (mi objeto de usuario de caso)

Si el tipo de campo es largo o int (o su TypeConverter lo convierte en largo o int), los métodos de inserción tratan 0 como no establecido al insertar el elemento.

Si el tipo de campo es Integer o Long (Object) (o su TypeConverter lo convierte en Integer o Long), los métodos de inserción tratan nulo como no establecido al insertar el elemento.

kunal khedkar
fuente
1
¿Podemos pasar la identificación personalizada a la entidad, aunque esté configurada en autoGenerate?
IgorGanapolsky
2
@Igor Ganapolsky Sí, pero la entrada se generará con esa identificación personalizada [el incremento automático no funcionará] Y si pasa la misma identificación nuevamente, arrojará la excepción 'Restricción ÚNICA fallida', por lo que debe pasar siempre una nueva identificación o hacerla [0 o nulo] y deje que el incremento automático haga esto por usted.
kunal khedkar
3
¿Por qué incluso dejas que el usuario ponga la identificación en el constructor si quieres autogenerar?
Hellcast
En Kotlin puede usar la clase de datos y escribir: val jack = User(name = "Jack", phone= 1)En este caso, puede eliminar 0 del constructor
user7856586
@hellcast Si no incluye la identificación en el constructor (como acabo de aprender de la manera difícil) cuando consulta la base de datos, no asignará el campo de identificación (solo será lo que haya inicializado en el constructor) desde Supongo que llama al mismo constructor cuando llena los campos del objeto.
Ali Hirani
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,
        "","","","")
}
Om Prakash Sharma
fuente
44
Si bien este fragmento de código puede ser la solución, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código.
Johan
44
Hay muchas respuestas como "usar @PrimaryKey(autoGenerate = true)": ¿su respuesta agrega algo nuevo a este hilo?
barbsan
sí, agrega - presenta cómo nulo cubre el campo autogenerado
Marian Paździoch
5

Por ejemplo, si tiene una usersentidad que desea almacenar, con campos (firstname, lastname , email)y desea una identificación autogenerada, haga esto.

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

La sala generará automáticamente e incrementará automáticamente el idcampo.

mayojava
fuente
22
Cada vez que creamos un nuevo objeto Usuarios, tendremos que pasar un campo de identificación. ¿Se puede evitar esto?
Aditya Ladwa
11
Sí, poner @PrimaryKey(autoGenerated = true) val id: Long? = nullfuera del constructor, en el cuerpo de la clase
Allan Veloso
1
@Magritte Care para elaborar más pls?
Ispam
2
@Ispam En mi respuesta anterior publiqué cómo debería verse la clase completa.
Allan Veloso
3
En realidad, simplemente puede poner 0 como ID. Room generará automáticamente una ID si ha configurado la opción @PrimaryKey.
romaneso
1

Anote su clase de entidad con el código anterior.

En java

@PrimaryKey(autoGenerate = true)
private int id;

En kotlin

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

La sala generará automáticamente e incrementará automáticamente el campo id.

Faxriddin Abdullayev
fuente