Come creare la chiave primaria come autoincremento per lib di persistenza ambiente


196

Sto creando un alimento di classe Entity (Room Persistence lib), dove voglio fare foodIdcome 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()
}

Come posso impostare foodIdun campo di incremento automatico?


4
Invece di 0.toDouble()usare puoi 0.0dichiararlo come doppio
RobCo

2
Come si crea una nuova istanza della classe Food? Specifichi manualmente l'ID o lo lasci vuoto?
Zookey,

3
Una nota per i futuri lettori: la chiave primaria deve essere 0 affinché Room lo consideri non impostato. Se usi qualsiasi altro valore predefinito (es. -1), Room non genererà automaticamente l'id.
Martin Melka,

Risposte:


375

Devi usare la autoGenerateproprietà

La tua annotazione chiave primaria dovrebbe essere così:

@PrimaryKey(autoGenerate = true)

Riferimento per PrimaryKey .


3
Grazie, stavo cercando AutoIncrement, ecco perché non sono riuscito a trovarlo.
chandil03,

Ehi @MatPag e se volessi due chiavi primarie in una tabella (chiavi primarie composite) e una delle chiavi primarie dovesse essere incrementata automaticamente? Come posso raggiungerlo? Puoi rispondere qui ?
Priyanka Alachiya,

1
@MatPeg Cosa succede se desidero avere un oggetto PrimaryKey auto-generato e uno che proviene da REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
Murt

@murt Hai bisogno di una chiave primaria composita, ma non puoi fare quello che vuoi ottenere. Leggi qui
MatPag il

Parte importante della documentazione collegata:Insert methods treat 0 as not-set while inserting the item.
Micha

127

Puoi aggiungere in @PrimaryKey(autoGenerate = true)questo modo:

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

35
foodIdnon deve essere nullo (ma può essere). Si potrebbero usare anche valori predefiniti, ad es. var foodId: Int = 0e l'autogenerato funzionerebbe correttamente.
Michał Baran,

8
@ MichałBaran, dal documento java, quando il tipo è un java primitivo into long, 0 è trattato come null-grado, quando il tipo è Integer o Long, null è il nullable. Dal momento che Kotlin Int quando non nullable funziona in JVM come int primitivo, allora hai ragione e var foodId: Int = 0funzionerai, ma var foodId: Int? = 0non funzionerà da Int? viene convertito in JVM come intero. @JMK, se lo rendi 0, DEVI rendere un nulla-annullabile intper il motivo di cui sopra.
Allan Veloso,

3
Puoi scrivere senza in un altro modo: val jack = User(name = "Jack", phone= 1)in questo caso puoi rimuovere 0 dal costruttore
user7856586

2
@AllanVeloso Puoi spiegare perché è foodIdstato inserito nel corpo e non nel costruttore?
Neeraj Sewani,

2
@ neer17 poiché foodId verrà generato automaticamente da Room al momento dell'inserimento, molto probabilmente non sarà utile averlo nel costruttore.
Allan Veloso,

42

Inserisci @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;
    }

}

durante la memorizzazione dei dati

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

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

tipo 1

Se non si passa valore per la chiave primaria, per impostazione predefinita sarà 0 o null.

tipo 2

Inserisci null o zero per l'id durante la creazione dell'oggetto (il mio oggetto utente del caso)

Se il tipo di campo è long o int (o se il suo TypeConverter lo converte in long o int), i metodi Insert trattano 0 come non impostato durante l'inserimento dell'elemento.

Se il tipo di campo è Integer o Long (Object) (o il suo TypeConverter lo converte in Integer o Long), i metodi Inserisci trattano null come non impostati durante l'inserimento dell'elemento.


1
Possiamo passare l'id personalizzato a Entity, anche se è impostato su autoGenerate?
IgorGanapolsky,

2
@Igor Ganapolsky Sì, ma la voce verrà modificata con quell'id personalizzato [l'incremento automatico non funzionerà] E se si passa di nuovo lo stesso id, verrà generata l'eccezione "Vincolo UNIQUE fallito", quindi è necessario passare sempre un nuovo id o renderlo [0 o null] e lascia che l'incremento automatico faccia questo lavoro per te.
kunal khedkar,

3
Perché stai anche lasciando che l'utente inserisca l'id nel costruttore se vuoi generare automaticamente?
hellcast,

In Kotlin puoi usare la classe di dati e scrivere: val jack = User(name = "Jack", phone= 1)In questo caso puoi rimuovere 0 dal costruttore
user7856586

@hellcast Se non includi l'id nel costruttore (come ho appena appreso nel modo più duro) quando esegui una query sul DB non assegnerà il campo ID (sarà semplicemente qualunque cosa tu lo inizializzi nel costruttore) poiché Presumo che chiami lo stesso costruttore quando si popolano i campi dell'oggetto.
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,
        "","","","")
}

4
Sebbene questo frammento di codice possa essere la soluzione, includendo una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e che queste persone potrebbero non conoscere i motivi del tuo suggerimento sul codice.
Johan

4
Ci sono molte risposte come "usa @PrimaryKey(autoGenerate = true)" - la tua risposta aggiunge qualcosa di nuovo a questa discussione?
Barbsan,

si aggiunge - presenta come null copre il campo autogenerato
Marian Paździoch,

5

Ad esempio, se si dispone di usersun'entità che si desidera archiviare, con campi (firstname, lastname , email)e si desidera un ID generato automaticamente, lo si fa.

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

La stanza quindi genererà e incrementerà automaticamente il idcampo.


22
Ogni volta che creiamo un nuovo oggetto Users, dovremo passare un campo ID. Questo può essere evitato?
Aditya Ladwa,

11
Sì, messo @PrimaryKey(autoGenerated = true) val id: Long? = nullfuori dal costruttore, sul corpo della classe
Allan Veloso,

1
@Magritte Care per elaborare più pls?
Ispam,

2
@Ispam Nella mia risposta sopra ho pubblicato come dovrebbe apparire la classe completa.
Allan Veloso,

3
In realtà, puoi semplicemente inserire 0 come ID. Room genererà automaticamente un ID se è stata impostata l'opzione @PrimaryKey.
romaneso,

1

Annota la tua classe Entity con il codice sopra.

In Java

@PrimaryKey(autoGenerate = true)
private int id;

A Kotlin

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

Room genererà quindi automaticamente e incrementerà automaticamente il campo ID.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.