Comment créer une clé primaire comme auto-incrémentation pour la librairie Room Persistence

197

Je crée une classe Food Entity (Room Persistence lib), où je veux créer une foodIdauto-incrémentation.

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

Comment puis-je définir foodIdun champ d'auto-incrémentation?

chandil03
la source
4
Au lieu de cela, 0.toDouble()vous pouvez utiliser 0.0do le déclarer comme un double
RobCo
2
Comment créez-vous une nouvelle instance de classe Food? Spécifiez-vous manuellement l'ID ou laissez-vous vide?
Zookey
3
Une note pour les futurs lecteurs - la clé primaire doit être 0 pour que Room la considère comme non définie. Si vous utilisez une autre valeur par défaut (par exemple -1), Room ne générera pas automatiquement l'ID.
Martin Melka

Réponses:

376

Vous devez utiliser la autoGeneratepropriété

Votre annotation de clé primaire doit ressembler à ceci:

@PrimaryKey(autoGenerate = true)

Référence pour PrimaryKey .

MatPag
la source
3
Merci, je cherchais autoIncrement, c'est pourquoi je n'ai pas pu trouver.
chandil03
Hey @MatPag et si je veux deux clés primaires dans une table (clés primaires composites) et l'une des clés primaires doit être incrémentée automatiquement? Comment puis-je y parvenir? Pouvez-vous répondre ici ?
Priyanka Alachiya
1
@MatPeg Que faire au cas où si je veux avoir une clé primaire qui est auto-générée et une qui vient de REST @Entity( primaryKeys = arrayOf(COLUMN_ID_LOCAL,COLUMN_ID_REMOTE))?
murt
@murt Vous avez besoin d'une clé primaire composite, mais vous ne pouvez pas faire ce que vous voulez. Lire ici
MatPag
Partie importante de la documentation liée:Insert methods treat 0 as not-set while inserting the item.
Micha
127

Vous pouvez ajouter @PrimaryKey(autoGenerate = true)comme ceci:

@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
la source
35
foodIdn'a pas besoin d'être nul (mais cela peut l'être). On pourrait également utiliser des valeurs par défaut, par exemple. var foodId: Int = 0et l'autogénération fonctionnerait correctement.
Michał Baran
8
@ MichałBaran, de la documentation java, lorsque le type est un java primitif intou long, 0 est traité comme nullable, lorsque le type est Integer ou Long, null est le nullable. Puisque Kotlin Int quand non-nullable fonctionne dans JVM comme int primitif, alors vous avez raison et var foodId: Int = 0fonctionnera, mais var foodId: Int? = 0ne fonctionnera pas depuis Int? est converti dans JVM en tant qu'Integer. @JMK, si vous le rendez 0, vous DEVEZ rendre un non-nullable intpour la raison mentionnée ci-dessus.
Allan Veloso
3
Vous pouvez écrire sans d'une autre manière: val jack = User(name = "Jack", phone= 1)Dans ce cas, vous pouvez supprimer 0 du constructeur
user7856586
2
@AllanVeloso Pouvez-vous expliquer pourquoi a foodIdété mis dans le corps et non dans le constructeur?
Neeraj Sewani
2
@ neer17 puisque le foodId sera généré automatiquement par Room lors de l'insertion, il ne sera probablement pas utile de l'avoir dans le constructeur.
Allan Veloso
42

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

}

lors du stockage des données

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

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

type 1

Si vous ne transmettez pas la valeur de la clé primaire, par défaut, elle sera 0 ou nulle.

type 2

Mettre null ou zéro pour l'id lors de la création de l'objet (objet utilisateur de mon cas)

Si le type de champ est long ou int (ou si son TypeConverter le convertit en long ou int), les méthodes Insert traitent 0 comme non défini lors de l'insertion de l'élément.

Si le type du champ est Integer ou Long (Object) (ou si son TypeConverter le convertit en Integer ou Long), les méthodes Insert traitent null comme non défini lors de l'insertion de l'élément.

kunal khedkar
la source
1
Pouvons-nous transmettre un identifiant personnalisé à Entity, même s'il est défini sur autoGenerate?
IgorGanapolsky
2
@Igor Ganapolsky Oui, mais l'entrée sera générée avec cet identifiant personnalisé [l'incrémentation automatique ne fonctionnera pas] Et si vous passez à nouveau le même identifiant, il lancera l'exception 'La contrainte UNIQUE a échoué', vous devez donc toujours passer un nouvel identifiant ou le rendre [0 ou null] et laissez l'auto-incrémentation faire ce travail pour vous.
kunal khedkar
3
Pourquoi laissez-vous même l'utilisateur mettre l'ID dans le constructeur si vous souhaitez générer automatiquement?
hellcast
Dans Kotlin, vous pouvez utiliser la classe de données et écrire: val jack = User(name = "Jack", phone= 1)Dans ce cas, vous pouvez supprimer 0 du constructeur
user7856586
@hellcast Si vous n'incluez pas l'id dans le constructeur (comme je viens de l'apprendre à la dure) lorsque vous interrogez la base de données, il n'attribuera pas le champ id (ce sera simplement celui avec lequel vous l'initialisez dans le constructeur) car Je suppose qu'il appelle le même constructeur lors du remplissage des champs de l'objet.
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
la source
4
Bien que cet extrait de code puisse être la solution, inclure une explication contribue vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question aux lecteurs à l'avenir, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
Johan
4
Il existe de nombreuses réponses comme «utiliser @PrimaryKey(autoGenerate = true)» - votre réponse ajoute-t-elle quelque chose de nouveau à ce fil?
barbsan
oui il ajoute - il présente comment nul couvre le champ autogène
Marian Paździoch
5

Par exemple, si vous avez une usersentité que vous souhaitez stocker, avec des champs (firstname, lastname , email)et que vous souhaitez un identifiant généré automatiquement, procédez ainsi.

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

Room génère alors et incrémente automatiquement le idchamp.

mayojava
la source
22
Chaque fois que nous créons un nouvel objet Users, nous devrons passer un champ id. Cela peut-il être évité?
Aditya Ladwa
11
Oui, mis en @PrimaryKey(autoGenerated = true) val id: Long? = nulldehors du constructeur, sur le corps de la classe
Allan Veloso
1
@Magritte Voulez-vous élaborer plus de pls?
Ispam
2
@Ispam Dans ma réponse ci-dessus, j'ai publié à quoi devrait ressembler la classe complète.
Allan Veloso le
3
En fait, vous pouvez simplement mettre 0 comme ID. Room générera automatiquement un identifiant si vous avez défini l'option @PrimaryKey.
romaneso
1

Annotez votre classe Entity avec le code ci-dessus.

En Java

@PrimaryKey(autoGenerate = true)
private int id;

À Kotlin

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

Room générera alors et incrémentera automatiquement le champ ID.

Faxriddin Abdullayev
la source